【发布时间】:2018-07-19 18:30:03
【问题描述】:
我有一堂课A
class A(object):
a = 1
def __init__(self):
self.b = 10
def foo(self):
print type(self).a
print self.b
然后我想创建一个类B,它等同于A,但类成员a的名称和值不同:
这是我尝试过的:
class A(object):
a = 1
def __init__(self):
self.b = 10
def foo(self):
print type(self).a
print self.b
A_dummy = type('A_dummy',(object,),{})
A_attrs = {attr:getattr(A,attr) for attr in dir(A) if (not attr in dir(A_dummy))}
B = type('B',(object,),A_attrs)
B.a = 2
a = A()
a.foo()
b = B()
b.foo()
但是我得到了一个错误:
File "test.py", line 31, in main
b.foo()
TypeError: unbound method foo() must be called with A instance as first argument (got nothing instead)
那么我该如何应对这类工作(创建一个存在类的副本)?也许需要一个元类?但我更喜欢的只是一个函数FooCopyClass,这样:
B = FooCopyClass('B',A)
A.a = 10
B.a = 100
print A.a # get 10 as output
print B.a # get 100 as output
在这种情况下,修改B的类成员不会影响A,反之亦然。
【问题讨论】:
-
注意:您使用的是 Python 2 这一事实在这里很重要;在 Python 3 上,您不会遇到未绑定方法的问题,因为没有这样的事情(在大多数情况下,您可以将一个函数从一个类复制到另一个类而不会抱怨,当您将它与新类一起使用时,例外情况是其中使用了 no-arg
super(),这要归功于使 no-argsuper()起作用所涉及的一些魔法)。 -
不要使用
dir,只需复制整个vars(A) -
@juanpa.arrivillaga:这也可能绕过导致未绑定方法问题的描述符协议问题。不过您需要使用
vars(A).copy(),因此您可以在生成的dict中编辑'a'的值,而无需更改A(您实际上无法在不复制的情况下更改结果,因为它是@ 987654340@/mappingproxy禁止重新分配)。 -
@ShadowRanger 我在使用
A_attrs = {attr:getattr(A,attr) for attr in vars(A)}时遇到了同样的错误 -
@springcc 不要使用
getattr,使用B = type("B", (object,), dict(vars(A)))。请注意,请注意每个班级都有一个__dict__,他们可能有__slots__,在这种情况下,您需要手动复制它。
标签: python metaprogramming python-2.x metaclass