我想用Python创建一个类,它接受构造函数中的一个参数,另一个Python类。复制类的实例应该具有原始类的所有属性和方法,而不必事先知道它们应该是什么。下面是一些几乎可以工作的代码:
import copy
class A():
l = 'a'
class Copy():
def __init__(self, original_class):
self = copy.deepcopy(original_class)
print(self.l)
c = Copy(A)
print(c.l)
构造函数中的print语句打印“a”,但最后一个语句给出错误AttributeError: Copy instance has no attribute 'l'
。在
这是一个有趣的问题,它指出了Python传递值语义的一个非常酷的特性,因为它与为什么原始代码不能正确工作以及为什么@martineau的解决方案工作得很好密切相关。在
为什么你写的代码不起作用
Python不支持纯粹的按引用传递或按值传递语义,而是执行以下操作:
为了看到这一点
^{pr2}$会发生什么?赋值创建一个局部
x
,然后为其赋值。一旦发生这种情况,作为参数传入的原始参数将不可访问。在但是,只要名称
x
绑定到传入的对象,您就可以修改属性,它将反映在传入的对象中。但是,在您将名称x
让给其他对象的那一刻起,该名称就不再绑定到您传入的原始参数。在为什么这和这里有关?在
如果您仔细注意
__init__
的签名,您会注意到它将self
作为参数。什么是self
?在通常,
self
是指对象实例。因此名称self
被绑定到对象实例。在这就是乐趣的开始。通过在代码中赋值给
self
,这个属性不再有效!当您离开
__init__
时,这个新的局部变量self
就超出了范围。这就是为什么做c.l
会在构造函数之外产生一个错误-您根本就没有实际分配给对象!在为什么@martineau的解决方案有效
@martineau只是利用这个行为来注意到
__dict__
属性存在于self
对象上,并为其赋值:现在,这是因为当Python看到名称空间操作符}没有被更改,但仍然引用对象实例。通过赋值给
.
时,当Python需要查找方法签名或属性时,__dict__
属性是Python调用的,也是因为{self.__dict__
,您将获得原始类的几乎完全相同的副本(“几乎精确”,因为即使是deepcopy
也有限制)。在这个故事的寓意应该很清楚:不要直接给
self
分配任何东西。相反,如果需要,只将分配给self
的属性。Python的元编程允许在这方面有很大的灵活性,在这方面您应该始终咨询the documentation。在我不确定你为什么要这么做,但你可能有你的理由。在
您可以利用正常继承:
例如:
您需要复制
__dict__
:相关问题 更多 >
编程相关推荐