方法对象与函数对象,Python类实例与类

Ank*_*wal 20 python methods class instance

我正在尝试验证实例属性和类属性之间的区别,如2012年11月1日的Python教程版本2.7.3,第9章:类,最后一行(源代码)所示:

实例对象的有效方法名称取决于其类.根据定义,作为函数对象的类的所有属性都定义其实例的相应方法.所以在我们的例子中,xf是一个有效的方法引用,因为MyClass.f是一个函数,但是xi不是,因为MyClass.i不是.但是xf与MyClass.f不同 - 它是一个方法对象,而不是一个函数对象.

我有这个:

class MyClass:    
   """A simple example class"""    
   i = 12345   
   def f():    
      return 'hello world'
Run Code Online (Sandbox Code Playgroud)

然后我这样做:

>>> x = MyClass()
>>> x.f
<bound method MyClass.f of <__main__.MyClass instance at 0x02BB8968>>
>>> MyClass.f
<unbound method MyClass.f>
>>> type(MyClass.f)
<type 'instancemethod'>
>>> type(x.f)
<type 'instancemethod'>
Run Code Online (Sandbox Code Playgroud)

需要注意的是这两种类型x.fMyClass.f为instancemethod.类型没有区别,但教程另有说法.有人可以澄清一下吗?

Gar*_*tty 24

绑定未绑定方法 - 解释.

...或者为什么Python有你指出的行为.

所以,首先,请注意这在3.x中是不同的.在3.x中,您将MyClass.f成为一个函数,并x.f作为一种方法 - 正如预期的那样.这种行为本质上是一个糟糕的设计决策,后来被改变了.

这样做的原因是Python有一个与大多数语言不同的方法的概念,它本质上是一个函数,第一个参数预先填充为instance(self).这种预填充是一种约束方法.

>>> x.foo
<bound method MyClass.foo of <__main__.MyClass instance at 0x1004989e0>>
Run Code Online (Sandbox Code Playgroud)

在Python 2.x及之前,有人认为未附加到实例的方法未绑定的方法,这是一个限制第一个参数(self)必须是对象实例的函数.然后准备将其绑定到实例并成为绑定方法.

>>> MyClass.foo
<unbound method MyClass.foo>
Run Code Online (Sandbox Code Playgroud)

随着时间的推移,很明显一个未绑定的方法实际上只是一个具有这个奇怪限制的函数,它并不重要(self必须是'正确'类型),因此它们被从语言中移除(在3.x中).这基本上是鸭子打字self,适合语言.

Python 3.3.0 (default, Dec  4 2012, 00:30:24) 
>>> x.foo
<bound method MyClass.foo of <__main__.MyClass object at 0x100858ed0>>
>>> MyClass.foo
<function MyClass.foo at 0x10084f9e0>
Run Code Online (Sandbox Code Playgroud)

进一步阅读.

这是一个(浓缩的,从内存中)解释,可以从他的"Python的历史"系列中的 Python创建者Guido van Rossum自己的口中全面阅读.


Mar*_*ers 13

该教程确实是错误的; 两者class.functionnameinstance.functionname返回一个方法对象.

接下来发生的是一个函数是一个描述符,__get__调用它们的方法,返回一个方法.方法有一个__func__指向原始函数的属性:

>>> class Foo(object):
...     def bar(self):
...         pass
... 
>>> Foo.bar
<unbound method Foo.bar>
>>> Foo().bar
<bound method Foo.bar of <__main__.Foo object at 0x1090d6f10>>
>>> # accessing the original function
...
>>> Foo.bar.__func__
<function bar at 0x1090cc488>
>>> # turning a function back into a method
...
>>> Foo.bar.__func__.__get__(None, Foo)
<unbound method Foo.bar>
>>> Foo.bar.__func__.__get__(Foo(), Foo)
<bound method Foo.bar of <__main__.Foo object at 0x1090d6f90>>
Run Code Online (Sandbox Code Playgroud)

这在Python 3中已经发生了变化; 有Foo.bar返回函数本身,非绑定方法不再存在:

$ python3.3
Python 3.3.0 (default, Sep 29 2012, 08:16:08) 
[GCC 4.2.1 Compatible Apple Clang 3.1 (tags/Apple/clang-318.0.58)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class Foo:
...     def bar(self):
...         pass
... 
>>> Foo.bar
<function Foo.bar at 0x105512dd0>
>>> Foo.bar.__get__(None, Foo)
<function Foo.bar at 0x105512dd0>
>>> Foo.bar.__get__(Foo(), Foo)
<bound method Foo.bar of <__main__.Foo object at 0x10552fe10>>
Run Code Online (Sandbox Code Playgroud)