为什么复制的对象与之前在 Python 中复制的对象具有相同的 ID?
Why copied objects have the same id as previously copied ones in Python?
我试图理解一个观察结果。
我有一个加载各种 Canvas
类 的应用程序,用户以后可以使用这些应用程序。这些 类 位于多个文件中。
例如.
canvas/
bw.py
colored.py
oil.py
我像这样导入、实例化和复制这些对象:
canvas_files = os.listdir('images')
imported_canvs = []
for canv in canvas_files:
canv = __import__(canv.split('.')[0], fromlist=['Canvas'])
try:
new_canv = canv.Canvas()
new_canv_copy = copy.copy(new_canv)
imported_canvs.append(new_canv_copy)
except AttributeError as ex:
pass
之后,用户使用 imported_canvs
列表中的每个 Canvas
对象。但是,当我两次导入和实例化这些对象时(运行 for
再次循环),我可以看到 id(new_canv_copy)
与之前导入和实例化的对象相同。
这不会是一个问题,除非每个 Canvas
都有对每个实例都是唯一的设置,而这目前没有发生。每当用户更改一个 Canvas
中的设置时,它们会在复制的一个中自动更改。
为什么会这样,我做错了什么?
copy.copy
执行浅拷贝,这意味着任何对象都将指向现有对象。如果你想让里面的对象也被克隆,你需要使用copy.deepcopy
。
仅使用 copy.copy()
创建一个浅拷贝。在使用 copy.deepcopy()
.
复制对象时,您可能希望使用深拷贝
你可以在这里详细阅读有什么区别:https://docs.python.org/2/library/copy.html
我不知道 canv.Canvas()
里面做了什么,所以当你 运行 相同的代码两次时,我无法自己尝试,所以很难说出发生了什么。
关于你在 运行 上的评论,for
循环多次广告得到相同的 id
...这可能不是 copy.copy
的问题,因为它复制顶级对象和 id
的顶级可变对象应该不同,但 id
的内部可变对象将保持不变,不像 copy.deepcopy
所有可变对象 id
应该不同。
可能是 __import__
本身的问题...
当您在 Python 中导入模块时,它只会导入一次。因此,当您发出模块的第一次导入时 'some_module_a.py' 它被导入,然后,当您发出同一模块的第二次导入时 'some_module_a.py' 它不会再次导入,而是对已导入模块的引用是 reused/returned.
因此,如果您需要多次重新导入同一模块,请在第一次导入它,然后使用 importlib.reload
再次真正导入它。
我试图理解一个观察结果。
我有一个加载各种 Canvas
类 的应用程序,用户以后可以使用这些应用程序。这些 类 位于多个文件中。
例如.
canvas/
bw.py
colored.py
oil.py
我像这样导入、实例化和复制这些对象:
canvas_files = os.listdir('images')
imported_canvs = []
for canv in canvas_files:
canv = __import__(canv.split('.')[0], fromlist=['Canvas'])
try:
new_canv = canv.Canvas()
new_canv_copy = copy.copy(new_canv)
imported_canvs.append(new_canv_copy)
except AttributeError as ex:
pass
之后,用户使用 imported_canvs
列表中的每个 Canvas
对象。但是,当我两次导入和实例化这些对象时(运行 for
再次循环),我可以看到 id(new_canv_copy)
与之前导入和实例化的对象相同。
这不会是一个问题,除非每个 Canvas
都有对每个实例都是唯一的设置,而这目前没有发生。每当用户更改一个 Canvas
中的设置时,它们会在复制的一个中自动更改。
为什么会这样,我做错了什么?
copy.copy
执行浅拷贝,这意味着任何对象都将指向现有对象。如果你想让里面的对象也被克隆,你需要使用copy.deepcopy
。
仅使用 copy.copy()
创建一个浅拷贝。在使用 copy.deepcopy()
.
你可以在这里详细阅读有什么区别:https://docs.python.org/2/library/copy.html
我不知道 canv.Canvas()
里面做了什么,所以当你 运行 相同的代码两次时,我无法自己尝试,所以很难说出发生了什么。
关于你在 运行 上的评论,for
循环多次广告得到相同的 id
...这可能不是 copy.copy
的问题,因为它复制顶级对象和 id
的顶级可变对象应该不同,但 id
的内部可变对象将保持不变,不像 copy.deepcopy
所有可变对象 id
应该不同。
可能是 __import__
本身的问题...
当您在 Python 中导入模块时,它只会导入一次。因此,当您发出模块的第一次导入时 'some_module_a.py' 它被导入,然后,当您发出同一模块的第二次导入时 'some_module_a.py' 它不会再次导入,而是对已导入模块的引用是 reused/returned.
因此,如果您需要多次重新导入同一模块,请在第一次导入它,然后使用 importlib.reload
再次真正导入它。