Python 描述符'__dict';对于对象不';无法使用类型()应用于对象
在Python3.6+中使用Python 描述符'__dict';对于对象不';无法使用类型()应用于对象,python,python-3.x,oop,inheritance,Python,Python 3.x,Oop,Inheritance,在Python3.6+中使用type()时,我的行为很奇怪。我正在使用它动态包装外部库中的所有类,在调用self.\uu dict\uu时出错。考虑下面的例子: class A(object): def __init__(self): print(self.__dict__) class B(A): def __init__(self): super(self.__class__, self).__init__() B() # this wor
type()
时,我的行为很奇怪。我正在使用它动态包装外部库中的所有类,在调用self.\uu dict\uu
时出错。考虑下面的例子:
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
如何使用type()
解决此问题
[TLDR:@fritzo的答案修复了错误,但此设计引入了其他继承问题。@juanpa.arrivillaga接受的答案提供了一个更好的解决方法]根据您关于希望动态执行此操作的评论,您可以使用
super
,但您必须了解其工作原理,super
为您提供了方法解析顺序中的下一个方法,因此您确实可以从mixin访问A
中的方法,但您必须正确使用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
不同的问题,但永远不要传递给
self.\uu类\uuuuuuu
或type(self)
到super
。我需要在非初始化\uuuuuu
方法中使用它,否则我会得到类型错误:super(type,obj):obj必须是类型的实例或子类型
。这个错误确实发生了。然而,孙辈是为工作而设计的,而你所做的却不是。您所做的操作与super
不兼容,并且在许多其他情况下都会中断,而不仅仅是super
或\uuuuuuuuu dict
。你真的应该重新设计你的包装;如果不这样做,问题将不断堆积,特别是当外部库发生变化时。根据程序其余部分的上下文,正确的解决方案可能是将C
aB
实例作为属性,或者使A
混合并从A
和B
继承多个。因此,我尝试使用mixin,但无法获得所需的功能。假设我有一个来自类C(B,a)的方法foo()
,其中B是我的mixin,a是一个外部类。在foo()
中,我想检查属性是否存在并调用B.foo
否则调用A.foo
。但是在B中,我没有访问A的类(和方法)的权限。对于一个类来说,这是很简单的,不需要类型
,但我希望以编程的方式对所有类都这样做。我该怎么写呢?谢谢你的回复!我正在加载一堆不同的a
s,所以通过编程(AFAIK)实现这一点的唯一方法是使用C=type('C',(Mixin,a),Mixin.\uu dict\uuuu.copy())
,这与我在OP中的内容有关。但是我在super().foo()
中得到类型错误,上面的注释中有类型错误。我可以用super(self.\uuu class\uuuuu,self)
来解决这个问题,但是根据我们上面的对话,这是不可取的。@luxon如果你能完整地描述一下你所面临的实际问题,那会有帮助的。这是一个类的例子,是的,我的意思是C=type('C',(Mixin,a),{})
。我在前面调用super()
时遇到了一个问题,但我相信这个解决方案是可行的。谢谢我将编辑并接受您的回复;我尽量避免编辑OP,因为其他人可能只是想用不同的问题调试错误消息。让我重申一下我的高级问题。有一个外部库,其中包含一组共享公共父类的类。我想重写每个类中的一些方法,以便在满足条件时执行自定义逻辑,否则使用原始逻辑。在这个上游库中可以添加新的类,所以我想动态地这样做(在您的示例中,假设有{A_1,A_2,…A_n},其中n是类的数量)@luxon,然后您可以使用一个类定义语句<代码>对于类列表中的cls:类X(混合,cls):通过代码>等