python - 对象的描述符“__dict__”不适用于使用 type() 的对象
问题描述
type()
在 Python 3.6+ 中使用时出现奇怪的行为。我正在使用它来动态包装来自外部库的所有类,并且在调用self.__dict__
. 考虑以下示例:
class A(object):
def __init__(self):
print(self.__dict__)
class B(A):
def __init__(self):
super(self.__class__, self).__init__()
B() # this works
但是当我做同样的事情时,type
我得到了这个奇怪的错误:
class A(object):
def __init__(self):
print(self.__dict__)
class B(object):
def __init__(self):
super(self.__class__, self).__init__()
# C is a class which is B that inherits from A
C = type('C', (A,), B.__dict__.copy())
C()
# TypeError: descriptor '__dict__' for 'B' objects doesn't apply to 'C' object
如何使用 using 解决此问题type()
?
[TLDR:@fritzo 的答案修复了错误,但这种设计引入了其他继承问题。@juanpa.arrivillaga 接受的答案提供了更好的解决方法]
解决方案
根据您对希望动态执行此操作的评论,您可以使用super
,但您必须了解它是如何工作的,super
为您提供方法解析顺序中的下一个方法,因此您可以访问A
mixin 中的方法,但您有正确使用super
:所以这样的事情可以工作:
In [1]: class Mixin:
...: def foo(self):
...: if hasattr(self, 'whatever'):
...: print("doing Mixin.foo stuff")
...: else:
...: return super().foo()
...:
In [2]: class A:
...: def foo(self):
...: print("doing A.foo stuff")
...:
In [3]: class C(Mixin, A):
...: pass
...:
In [4]: c = C()
In [5]: c.foo()
doing A.foo stuff
In [6]: c.whatever = 42
In [7]: c.foo()
doing Mixin.foo stuff
但是,我不确定这是多么值得推荐。但这是可能的。
请注意,动态,我的意思是这样的工作:
In [9]: class Mixin:
...: def foo(self):
...: if hasattr(self, 'whatever'):
...: print("doing Mixin.foo stuff")
...: else:
...: return super().foo()
...: class A:
...: pass
...:
...: class B:
...: def foo(self):
...: print("doing B.foo stuff")
...:
...: class C(Mixin, A, B):
...: pass
...:
In [10]: c = C()
In [11]: c.foo()
doing B.foo stuff
In [12]: c.whatever = 42
In [13]: c.foo()
doing Mixin.foo stuff