python 3中的”函数”、”方法”和”绑定方法”有什么区别? ‘function’, ‘method’ and ‘bound method’

What's the difference between a 'function', 'method' and 'bound method' in Python 3?

我观察到至少3种与Python3中的函数相关的类型:

1
2
3
4
5
6
7
8
9
>>> class A():
...  def f(): pass
...
>>> A.f
<function A.f at 0x7fcaef304268>
>>> A().f
<bound method A.f of <__main__.A object at 0x7fcaef2fae80  
>>> set.union
<method 'union' of 'set' objects>

我想知道"函数"、"方法"和"绑定方法"有什么区别?"method"是不是与python 2中的"unbound method"等效的类型?


Is 'method' a type equivalent to 'unbound method' in Python 2?

有点像,但不是真的。它是在C代码中定义的method_descriptor对象。它是一个未绑定的方法,但不是您在Python2中找到的那种方法。

对于编写C的Python类型,所有"方法"实际上都是C函数。您发现的对象是一个特殊的对象,您可以使用它来调用给定实例和其他参数的函数,就像function对象用于自定义python类一样。对象在PyMethodDescr_Type结构中用c定义。它实现了描述符协议,就像函数一样。

python定义了其他几个这样的描述符类型;如果使用__slots__,那么每个属性都是member_descriptor类型的dsescriptor(参见PyMemberDescr_Type结构),而classmethodpropertystaticmethod可能是更有名的描述符对象。

在python 2中,绑定和未绑定方法实际上只是一种类型,instancemethod(由PyMethod_Type结构定义);如果设置了__self__(im_self属性,它将报告为绑定。在Python3中,使用函数作为描述符,在没有__self__集的情况下不会生成方法对象;相反,在没有实例的情况下调用function.__get__(),只会再次返回函数。

python 2返回未绑定方法的唯一原因是强制执行类型检查;第一个参数必须是类(或其子类)的实例。对于支持duck类型的python代码来说,这并没有多大意义,因此在python 3中取消了限制。但是,对于不能使用duck类型的C代码,仍然需要限制类型,这就是为什么C类型仍然返回强制执行此限制的method_descriptor对象的原因。