首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >方法对象与函数对象,Python类实例与类

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

Stack Overflow用户
提问于 2013-01-12 22:57:07
回答 2查看 15.5K关注 0票数 23

我正试图验证Python教程2.7.3版本(2012年11月1日,第9章:类,第66页最后一行(https://docs.python.org/2/tutorial/classes.html#instance-objects))中列出的实例属性和类属性之间的区别:

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

我有这个:

代码语言:javascript
运行
复制
class MyClass:    
   """A simple example class"""    
   i = 12345   
   def f():    
      return 'hello world'

然后我就这么做:

代码语言:javascript
运行
复制
>>> 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'>

注意,x.fMyClass.f的类型都是instancemethod。类型没有差别,但教程却不这么说。有人能澄清一下吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-01-12 23:04:06

绑定与未绑定方法-一个解释。

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

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

其原因是Python有一个与大多数语言不同的方法的概念,它本质上是一个函数,它的第一个参数预填充为实例(self)。这种预填充法是一种装订方法.

代码语言:javascript
运行
复制
>>> x.foo
<bound method MyClass.foo of <__main__.MyClass instance at 0x1004989e0>>

在Python2.x和之前的版本中,可以推断没有附加到实例的方法是一个未绑定的方法,它是一个函数,其限制是第一个参数(self)必须是对象的一个实例。然后,就可以将其绑定到实例并成为绑定方法。

代码语言:javascript
运行
复制
>>> MyClass.foo
<unbound method MyClass.foo>

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

代码语言:javascript
运行
复制
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>

进一步阅读。

这是一个(从内存中浓缩的)解释,可以从Python创建者Guido在他的“Python历史”系列中自己的嘴中完整阅读。

票数 29
EN

Stack Overflow用户

发布于 2013-01-12 23:01:12

本教程确实错了;class.functionnameinstance.functionname都返回一个方法对象。

所发生的是一个函数是一个描述符,它们的__get__方法被调用,返回一个方法。方法具有指向原始函数的__func__属性:

代码语言:javascript
运行
复制
>>> 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>>

不过,在Python3中,这一切都已改变;在那里,Foo.bar返回函数本身,不再存在未绑定的方法:

代码语言:javascript
运行
复制
$ 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>>
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14298844

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档