【发布时间】:2012-02-09 00:53:46
【问题描述】:
根据文档,super(cls, obj) 返回
将方法调用委托给父级或兄弟级的代理对象 cls 类型的类
我理解super() 提供此功能的原因,但我需要一些稍微不同的东西:我需要创建一个代理对象,将方法调用(和属性查找)委托给类cls 本身;和super 一样,如果cls 没有实现方法/属性,我的代理应该继续查看MRO 顺序(new 而不是original班级)。有没有我可以编写的函数来实现这一点?
例子:
class X:
def act():
#...
class Y:
def act():
#...
class A(X, Y):
def act():
#...
class B(X, Y):
def act():
#...
class C(A, B):
def act():
#...
c = C()
b = some_magic_function(B, c)
# `b` needs to delegate calls to `act` to B, and look up attribute `s` in B
# I will pass `b` somewhere else, and have no control over it
当然,我可以使用 b = super(A, c),但这取决于了解确切的类层次结构和B 在 MRO 中遵循 A 的事实。如果这两个假设中的任何一个在未来发生变化,它就会悄然崩溃。 (注意super 没有做出任何这样的假设!)
如果我只需要拨打b.act(),我可以使用B.act(c)。但是我正在将b 传递给其他人,并且不知道他们会用它做什么。我需要确保它不会背叛我,并在某个时候开始表现得像 class C 的实例。
一个单独的问题,super()(在 Python 3.2 中)的文档只讨论了它的方法委托,并没有说明代理的属性查找也以相同的方式执行。是不小心遗漏了吗?
编辑
更新后的委托方法也适用于以下示例:
class A:
def f(self):
print('A.f')
def h(self):
print('A.h')
self.f()
class B(A):
def g(self):
self.f()
print('B.g')
def f(self):
print('B.f')
def t(self):
super().h()
a_true = A()
# instance of A ends up executing A.f
a_true.h()
b = B()
a_proxy = Delegate(A, b)
# *unlike* super(), the updated `Delegate` implementation would call A.f, not B.f
a_proxy.h()
请注意,更新后的 class Delegate 比 super() 更接近我想要的,原因有两个:
super()只代理第一个呼叫;后续调用将照常进行,因为此时使用的是对象,而不是其代理。super()不允许属性访问。
因此,我提出的问题在 Python 中有一个(几乎)完美的答案。
事实证明,在更高的层次上,我试图做一些我不应该做的事情 (see my comments here)。
【问题讨论】:
-
你不能确保它不像 C 类的实例,因为它就是这样。如果您真的非常想要一个 B() 的实例,我建议您只需创建一个具有所需属性的 B 实例。您可以从 C 复制它们。
-
@LennartRegebro:好吧,我没有要求
b是class C的一个实例,事实上它不是;它是一个完全不同的类的实例(class Delegate在 Sven 解决方案的情况下,class super在内置super()的情况下,等等)。除此之外,您可能是对的,b不能被阻止背叛其(间接)访问class C实例方法和属性的能力。如果是这样,您能否举例说明 Sven 的Delegate(B, c)将如何充当class C的实例?
标签: python python-3.x multiple-inheritance superclass super