首页 > 解决方案 > 对象的描述符“__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 接受的答案提供了更好的解决方法]

标签: pythonpython-3.xoopinheritance

解决方案


根据您对希望动态执行此操作的评论,您可以使用super,但您必须了解它是如何工作的,super为您提供方法解析顺序中的下一个方法,因此您可以访问Amixin 中的方法,但您有正确使用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

推荐阅读