我想在Python中创建一个在构造函数中使用单个参数的类,另一个Python类。 Copy类的实例应该具有原始类的所有属性和方法,而不知道它们应该事先是什么。这里有一些几乎可行的代码:
cnode=for /d /r . %d in (node_modules) do @if exist "%d" rm -rf "%d"
构造函数中的print语句打印' a',但最后一个给出错误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)
。
答案 0 :(得分:1)
我不确定你为什么要这样做,但你可能有你的理由。
您可以利用正常继承:
例如:
class A(object):
l = 'a'
class C(object):
l = 'c'
def createClass(cls):
class B(cls):
pass
return B
cls = createClass(C) # or A or whatever
print cls.l
=> result: 'c'
答案 1 :(得分:1)
您需要复制__dict__
:
import copy
class A():
l = 'a'
class Copy():
def __init__(self, original_class):
self.__dict__ = copy.deepcopy(original_class.__dict__)
print(self.l)
c = Copy(A) # -> a
print(c.l) # -> a
答案 2 :(得分:1)
这是一个有趣的问题,指出了Python的值传递语义的一个非常酷的特性,因为它与原始代码无法正常工作的原因密切相关,以及为什么@ martineau的解决方案运行良好。
Python不支持纯传递引用或按值传递语义 - 相反,它执行以下操作:
# Assume x is an object
def f(x):
# doing the following modifies `x` globally
x.attribute = 5
# but doing an assignment only modifies x locally!
x = 10
print(x)
要看到这一点,
# example
class Example(object):
def __init__(self):
pass
x = Example()
print(x)
>>> <__main__.Example instance at 0x020DC4E0>
f(e) # will print the value of x inside `f` after assignment
>>> 10
print(x) # This is unchanged
>>> <__main__.Example instance at 0x020DC4E0>
e.attribute # But somehow this exists!
>>> 5
会发生什么?分配创建本地 x
,然后为其分配值。一旦发生这种情况,作为参数传入的原始参数将无法访问。
但是,只要 name x
绑定到传入的对象,就可以修改属性,它将反映在您传入的对象中。将名称x
'弃用'给其他东西,但是,该名称不再绑定到您传入的原始参数。
为什么这里有关系?
如果您特别注意__init__
的签名,您会注意到它需要self
作为参数。什么是self
?
通常,self
指的是对象实例。因此名称self
绑定到对象实例。
这是有趣的开始。 通过在代码中分配self
,此属性不再成立!
def __init__(self, original_class):
# The name `self` is no longer bound to the object instance,
# but is now a local variable!
self = copy.deepcopy(original_class)
print(self.l) # this is why this works!
离开__init__
的那一刻,这个新的本地变量self
超出了范围。这就是为什么做c.l
会在构造函数之外产生错误 - 你从来没有真正分配给对象!
@martineau只是利用这种行为来注意__dict__
对象上存在self
属性,并分配给它:
class Copy():
def __init__(self, original_class):
# modifying attributes modifies the object self refers to!
self.__dict__ = copy.deepcopy(original_class.__dict__)
print(self.l)
这现在有效,因为__dict__
属性是Python在Python看到命名空间运算符.
时需要查找方法签名或属性时调用的属性,也是因为self
没有已更改但仍引用对象实例。通过分配到self.__dict__
,您可以获得原始类的几乎完全相同的副本(“几乎完全”,因为即使deepcopy
也有限制)。
故事的寓意应该清楚:永远不要直接向self
分配任何内容。相反,如果您需要,仅分配给self
的属性。 Python的元编程在这方面具有很大的灵活性,你应该在这方面咨询the documentation。