函数由def
语句创建,或由lambda
. 在 Python 2 中,当函数出现在class
语句的主体中(或传递给type
类构造调用)时,它会被转换为未绑定的方法。(Python 3 没有未绑定的方法;见下文。)在类实例上访问函数时,它会转换为绑定的方法,该方法会自动将实例作为第一个self
参数提供给该方法。
def f1(self):
pass
这f1
是一个函数。
class C(object):
f1 = f1
现在C.f1
是一个未绑定的方法。
>>> C.f1
<unbound method C.f1>
>>> C.f1.im_func is f1
True
我们还可以使用type
类构造函数:
>>> C2 = type('C2', (object,), {'f1': f1})
>>> C2.f1
<unbound method C2.f1>
我们可以f1
手动转换为未绑定的方法:
>>> import types
>>> types.MethodType(f1, None, C)
<unbound method C.f1>
未绑定的方法通过对类实例的访问进行绑定:
>>> C().f1
<bound method C.f1 of <__main__.C object at 0x2abeecf87250>>
访问通过描述符协议转换为调用:
>>> C.f1.__get__(C(), C)
<bound method C.f1 of <__main__.C object at 0x2abeecf871d0>>
结合这些:
>>> types.MethodType(f1, None, C).__get__(C(), C)
<bound method C.f1 of <__main__.C object at 0x2abeecf87310>>
或直接:
>>> types.MethodType(f1, C(), C)
<bound method C.f1 of <__main__.C object at 0x2abeecf871d0>>
函数和未绑定方法的主要区别在于后者知道它绑定到哪个类;调用或绑定未绑定的方法需要其类类型的实例:
>>> f1(None)
>>> C.f1(None)
TypeError: unbound method f1() must be called with C instance as first argument (got NoneType instance instead)
>>> class D(object): pass
>>> f1.__get__(D(), D)
<bound method D.f1 of <__main__.D object at 0x7f6c98cfe290>>
>>> C.f1.__get__(D(), D)
<unbound method C.f1>
由于函数和未绑定方法之间的区别非常小,Python 3摆脱了这种区别;在 Python 3 下,访问类实例上的函数只会为您提供函数本身:
>>> C.f1
<function f1 at 0x7fdd06c4cd40>
>>> C.f1 is f1
True
那么,在 Python 2 和 Python 3 中,这三个是等价的:
f1(C())
C.f1(C())
C().f1()
将函数绑定到实例具有将其第一个参数(通常称为self
)固定到实例的效果。因此,绑定方法C().f1
等效于以下任一方法:
(lamdba *args, **kwargs: f1(C(), *args, **kwargs))
functools.partial(f1, C())