Python 3 中的 'function'、'method' 和 'bound method' 有什么区别?

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

我在 Python 3:

中观察到至少 3 种与函数相关的类型
>>> 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>

我想知道 'function'、'method' 和 'bound method' 之间有什么区别? 'method' 是等同于 Python 2 中的 'unbound method' 的类型吗?

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

请稍等一下。但不是真的。它是一个用 C 代码定义的 method_descriptor 对象。这是一个未绑定的方法,但不是您在 Python 2.

中找到的那种方法

对于 Python 写成 C 的类型,所有 'methods' 都是真正的 C 函数。您找到的 <method 'name' of 'type' objects> 对象是一个特殊对象,您可以使用它来调用给定实例和更多参数的函数,就像 function 对象对自定义 Python classes 所做的那样.该对象在 PyMethodDescr_Type structure. It implements the descriptor protocol 中用 C 定义,就像函数一样。

Python 定义了其他几个这样的描述符类型;如果您使用 __slots__, each attribute is a dsescriptor of type member_descriptor (see the PyMemberDescr_Type structure),而 classmethodpropertystaticmethod 可能是更广为人知的描述符对象。

在Python 2、绑定和未绑定方法实际上只是一个类型,instancemethod(由PyMethod_Type structure定义);如果设置了 __self__ (im_self) 属性,它将报告为绑定。在 Python 3 中,使用函数作为描述符在没有设置 __self__ 的情况下根本不会生成方法对象;而不是在没有实例的情况下调用 function.__get__() 只是再次 return 函数。

Python 2 return 未绑定方法的唯一原因是强制执行类型检查;第一个参数必须是 class 的实例(或其子 class )。这对于支持 duck-typing 的 Python 代码没有多大意义,因此在 Python 3 中删除了限制。但是,对于 C 代码,您不能使用 duck-typing,您仍然必须限制类型,这就是为什么 C-types 仍然 return a method_descriptor强制执行此限制的对象。