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

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

问题描述

由于讨论了此答案的评论主题,所以我提出这个问题。我是90%的方式让我的头部轮到它。

  In [1]:class A(object): #类名为'A'
...:def f1(self):pass
...:
在[2]中:a = A()#一个实例

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

 在[3]中:a.f1#a bound method 
Out [3]:<< bound method a.f1 of< __main __。0x039BE870>的对象>
In [4]:A.f1#一个未绑定的方法
Out [4]:< unbound method A.f1>
In [5]:a .__ dict __ ['f1']#不存在
KeyError:'f1'
In [6]:A .__ dict __ ['f1']#a函数
Out [6]:< function __main __。f1>

绑定方法 unbound方法有什么区别 function 对象,所有这些对象都由f1来描述?我们如何称呼这三个对象?他们怎样才能相互转化?关于这个东西的文档很难理解。

解决方案 def 语句创建,或 lambda 。在Python 2下,当一个函数出现在语句的正文中(或者传递给类型类构造调用),它将转换为未绑定的方法。 (Python 3没有未绑定的方法,参见下面的内容。)当一个函数在类实例上被访问时,它被转换成一个绑定方法,自动将实例作为第一个方法提供给方法 self 参数。

  def f1(self):
通过

这里 f1 是一个函数

  class C(object):
f1 = f1

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

 >>> C.f1 
>>> C.f1.im_func是f1
True

我们也可以使用<$ c $

 >>>类型类构造函数: C2 = type('C2',(object,),{'f1':f1})
>>> C2.f1
<未绑定方法C2.f1>

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

 >>>导入类型
>>> types.MethodType(f1,None,C)

未绑定的方法受到类实例的访问限制:

 >>> C()。f1 
< __ main __的边界方法C.f1。0x2abeecf87250处的C对象>>

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

 >>> C.f1 .__获得__(C(),C)
<< __的绑定方法C.f1。0x2abeecf871d0的C对象>>

合并这些:

 >>> types.MethodType(f1,None,C).__ get __(C(),C)
<< __ main __的bound method C.f1。0x2abeecf87310的C object>>

或直接:

 >>>类型。方法类型(f1,C(),C)
<< __的边界方法C.f1 __。0x2abeecf871d0处的C对象>>

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

 >>> f1(无)
>>> C.f1(None)
TypeError:必须使用C实例作为第一个参数调用f1()的非绑定方法(改为获得NoneType实例)
>>> D类(对象):pass
>>> f1 .__得到__(D(),D)
<< __的边界方法D.f1。0x7f6c98cfe290的D对象>>
>>> C.f1 .__ get __(D(),D)

由于函数和非绑定方法之间的差异非常小,因此Python 3摆脱了这种差别;在Python 3下访问类实例上的函数只会给你自己的函数:

 >>> C.f1 
<0x7fdd06c4cd40时的函数f1>>
>>> C.f1是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())


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天全站免登陆