我们可以使用super()在MRO中的类方法之间测试身份吗? [英] Can we use super() to test identity between class methods in the MRO?
问题描述
请考虑以下示例:
class A:
def m():
pass
class B(A):
pass
以及以下终端输出:
>>> b = B()
>>> b.m
<bound method A.m of <__main__.B object at 0x000001EFFF24C748>>
>>> super(b.__class__, b).m
<bound method A.m of <__main__.B object at 0x000001EFFF24C748>>
>>> b.m is super(b.__class__, b).m
False
>>> b.m == super(b.__class__, b).m
True
为什么它们相等但不相同?继承时是否制作了该方法的副本?
Why are they equal but not identical? Is a copy of the method made when it is inherited?
是否有更好的方法来测试子类是否重写了父方法?
Are there better ways to test whether a child class has overridden a parent method?
推荐答案
使用super(b.__class__, b)
会产生一个实现__getattr__
方法的对象,该方法将从位置1开始跳过__mro__
属性(跳过当前类)并查找具有指定属性的第一个类.然后它将返回该绑定方法.有关更好的解释,请参见此答案.
Using super(b.__class__, b)
produces an object that implements a __getattr__
method that will go up the __mro__
attribute starting at position 1 (skipping the current class) and look for the first class that has the specified attribute. It will then return that bound method. For a better explanation see this answer.
了解所有功能也是以下内容的描述符
Knowing that all functions are also descriptors the following
class A:
def m(self):
pass
创建一个具有属性m
的对象A
,该属性将是一个函数和描述符.初始化类A
的对象a
时,基本上会产生a.m = A.m.__get__(a)
,该对象将生成以a
作为第一个参数self
的绑定方法.
creates an object A
with the attribute m
which will be a function and descriptor. When you initialize an object a
of class A
, it will basically result in a.m = A.m.__get__(a)
which produces the bound method that has a
as the first argument self
.
现在,由于super
还会检索绑定方法,因此正在检查的是A.m.__get__(a)
的两个实例之间的身份,从而产生终端输出:
Now since super
also retrieves bound methods what is being checked is the identity between 2 instances of A.m.__get__(a)
producing your terminal output:
>>> A.m.__get__(a)
<bound method A.m of <__main__.A object at 0x...>>
>>> A.m.__get__(a) is A.m.__get__(a)
False
因此对类描述符m
的2次调用会生成不同的绑定实例,这就是为什么身份检查失败的原因.相反,您应该测试产生绑定方法的函数的身份.幸运的是,绑定方法包含返回原始函数的__func__
属性.因此,要查找任何实例的类是否重写了继承的函数,而又不仅仅知道函数的实例和名称,可以执行以下操作:
So 2 calls to the class descriptor m
produce different bound instances and it is why the identity check fails. Instead you should test the identity of the functions that produced the bound methods. Luckily a bound method contains the __func__
attribute that returns the original function. So to lookup whether any instance's class has overridden an inherited function without knowing more than just the instance and name of the function you can do:
>>> a.__class__.m is super(a.__class__, a).m.__func__
True
这篇关于我们可以使用super()在MRO中的类方法之间测试身份吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!