我们可以使用super()在MRO中的类方法之间测试身份吗? [英] Can we use super() to test identity between class methods in the MRO?

查看:76
本文介绍了我们可以使用super()在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆