函数、未绑定方法和绑定方法之间有什么区别? [英] What is the difference between a function, an unbound method and a bound method?

查看:31
本文介绍了函数、未绑定方法和绑定方法之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我问这个问题是因为对这个答案的评论线程进行了讨论.我已经完成了 90% 的工作.

In [1]: class A(object): # class named 'A'...: def f1(self): 通过...:In [2]: a = A() # 一个实例

f1 以三种不同的形式存在:

In [3]: a.f1 # 一个绑定方法Out[3]: >在 [4]: A.f1 # 一个未绑定的方法Out[4]:<未绑定方法A.f1>在 [5]: a.__dict__['f1'] # 不存在键错误:'f1'In [6]: A.__dict__['f1'] # 一个函数输出[6]:<function __main__.f1>

绑定方法未绑定方法函数对象之间有什么区别,所有这些都用f1来描述?如何称呼这三个对象?它们如何相互转化?关于这些内容的文档很难理解.

解决方案

functiondef 语句创建,或者由 lambda 创建.在 Python 2 下,当一个函数出现在 class 语句的主体中(或被传递给一个 type 类构造调用)时,它被转换为一个未绑定的方法.(Python 3 没有未绑定的方法;见下文.)当在类实例上访问一个函数时,它被转换为一个绑定方法,它自动将实例提供给方法作为第一个self 参数.

def f1(self):经过

这里的f1是一个函数.

C 类(对象):f1 = f1

现在 C.f1 是一个未绑定的方法.

<预><代码>>>>C.f1<未绑定方法C.f1>>>>C.f1.im_func 是 f1真的

我们也可以使用type类构造函数:

<预><代码>>>>C2 = type('C2', (object,), {'f1': f1})>>>C2.f1<未绑定方法C2.f1>

我们可以手动将 f1 转换为未绑定的方法:

<预><代码>>>>进口类型>>>types.MethodType(f1, None, C)<未绑定方法C.f1>

未绑定的方法通过对类实例的访问来绑定:

<预><代码>>>>C().f1<0x2abeecf87250处<__main__.C对象的绑定方法C.f1>

访问通过描述符协议转化为调用:

<预><代码>>>>C.f1.__get__(C(), C)<0x2abeecf871d0处<__main__.C对象的绑定方法C.f1>

结合这些:

<预><代码>>>>types.MethodType(f1, None, C).__get__(C(), C)<在0x2abeecf87310处<__main__.C对象的绑定方法C.f1>>

或直接:

<预><代码>>>>types.MethodType(f1, C(), C)<0x2abeecf871d0处<__main__.C对象的绑定方法C.f1>

函数和未绑定方法的主要区别在于后者知道它绑定到哪个类;调用或绑定未绑定的方法需要其类类型的实例:

<预><代码>>>>f1(无)>>>C.f1(无)类型错误:必须使用 C 实例作为第一个参数调用未绑定的方法 f1()(改为使用 NoneType 实例)>>>D类(对象):通过>>>f1.__get__(D(), D)<0x7f6c98cfe290处<__main__.D对象的绑定方法D.f1>>>>>C.f1.__get__(D(), D)<未绑定方法C.f1>

由于函数和未绑定方法之间的区别非常小,Python 3 摆脱区别;在 Python 3 下访问类实例上的函数只会为您提供函数本身:

<预><代码>>>>C.f1<函数 f1 在 0x7fdd06c4cd40>>>>C.f1 是 f1真的

在 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())

I'm asking this question because of a discussion on the comment thread of this answer. I'm 90% of the way to getting my head round it.

In [1]: class A(object):  # class named 'A'
   ...:     def f1(self): pass
   ...:
In [2]: a = A()  # an instance

f1 exists in three different forms:

In [3]: a.f1  # a bound method
Out[3]: <bound method a.f1 of <__main__.A object at 0x039BE870>>
In [4]: A.f1  # an unbound method
Out[4]: <unbound method A.f1>
In [5]: a.__dict__['f1']  # doesn't exist
KeyError: 'f1'
In [6]: A.__dict__['f1']  # a function
Out[6]: <function __main__.f1>

What is the difference between the bound method, unbound method and function objects, all of which are described by f1? How does one call these three objects? How can they be transformed into each other? The documentation on this stuff is quite hard to understand.

解决方案

A function is created by the def statement, or by lambda. Under Python 2, when a function appears within the body of a class statement (or is passed to a type class construction call), it is transformed into an unbound method. (Python 3 doesn't have unbound methods; see below.) When a function is accessed on a class instance, it is transformed into a bound method, that automatically supplies the instance to the method as the first self parameter.

def f1(self):
    pass

Here f1 is a function.

class C(object):
    f1 = f1

Now C.f1 is an unbound method.

>>> C.f1
<unbound method C.f1>
>>> C.f1.im_func is f1
True

We can also use the type class constructor:

>>> C2 = type('C2', (object,), {'f1': f1})
>>> C2.f1
<unbound method C2.f1>

We can convert f1 to an unbound method manually:

>>> import types
>>> types.MethodType(f1, None, C)
<unbound method C.f1>

Unbound methods are bound by access on a class instance:

>>> C().f1
<bound method C.f1 of <__main__.C object at 0x2abeecf87250>>

Access is translated into calling through the descriptor protocol:

>>> C.f1.__get__(C(), C)
<bound method C.f1 of <__main__.C object at 0x2abeecf871d0>>

Combining these:

>>> types.MethodType(f1, None, C).__get__(C(), C)
<bound method C.f1 of <__main__.C object at 0x2abeecf87310>>

Or directly:

>>> types.MethodType(f1, C(), C)                
<bound method C.f1 of <__main__.C object at 0x2abeecf871d0>>

The main difference between a function and an unbound method is that the latter knows which class it is bound to; calling or binding an unbound method requires an instance of its class type:

>>> 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>

Since the difference between a function and an unbound method is pretty minimal, Python 3 gets rid of the distinction; under Python 3 accessing a function on a class instance just gives you the function itself:

>>> C.f1
<function f1 at 0x7fdd06c4cd40>
>>> C.f1 is f1
True

In both Python 2 and Python 3, then, these three are equivalent:

f1(C())
C.f1(C())
C().f1()

Binding a function to an instance has the effect of fixing its first parameter (conventionally called self) to the instance. Thus the bound method C().f1 is equivalent to either of:

(lamdba *args, **kwargs: f1(C(), *args, **kwargs))
functools.partial(f1, C())

这篇关于函数、未绑定方法和绑定方法之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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