我试图验证实例属性和类属性之间的区别,如2012年11月1日的Python教程版本2。3。3,第9章:类,最后一行(源)所示:
Valid method names of an instance object depend on its class. By
definition, all attributes of a class that are function objects define
corresponding methods of its instances. So in our example, x.f is a
valid method reference, since MyClass.f is a function, but x.i is not,
since MyClass.i is not. But x.f is not the same thing as MyClass.f —
it is a method object, not a function object.
我有这个:
class MyClass:
"""A simple example class"""
i = 12345
def f():
return 'hello world'
然后我这样做:
>>> x = MyClass()
>>> x.f
>
>>> MyClass.f
>>> type(MyClass.f)
>>> type(x.f)
请注意,x.f和MyClass.f的类型都是instancemethod。 类型没有区别,但教程另有说法。 有人可以澄清一下吗?
绑定与未绑定方法 - 解释。
...或者为什么Python有你指出的行为。
所以,首先,请注意这在3.x中是不同的。在3.x中,您将获得MyClass.f作为函数,并将x.f作为方法 - 正如预期的那样。这种行为本质上是一个糟糕的设计决策,后来被改变了。
这样做的原因是Python有一个与大多数语言不同的方法的概念,它本质上是一个函数,第一个参数预先填充为实例(self)。这种预填充是一种约束方法。
>>> x.foo
>
在Python 2.x及之前,有人认为未附加到实例的方法是未绑定的方法,这是一个限制第一个参数(self)必须是对象实例的函数。然后准备将其绑定到实例并成为绑定方法。
>>> MyClass.foo
随着时间的推移,很明显一个未绑定的方法实际上只是一个具有这个奇怪限制的函数并不重要(self必须是'正确'类型),所以它们被从语言中移除(在3中。 X)。这基本上是鸭子打字self,适合这种语言。
Python 3.3.0 (default, Dec 4 2012, 00:30:24)
>>> x.foo
>
>>> MyClass.foo
进一步阅读。
这是一个(浓缩的,从内存中)解释,可以从Python创建者Guido van Rossum在他的"Python的历史"系列中自己阅读。
该教程确实是错误的; class.functionname和instance.functionname都返回一个方法对象。
接下来发生的是函数是一个描述符,并调用它们的__get__方法,返回一个方法。方法的__func__属性指向原始函数:
>>> class Foo(object):
... def bar(self):
... pass
...
>>> Foo.bar
>>> Foo().bar
>
>>> # accessing the original function
...
>>> Foo.bar.__func__
>>> # turning a function back into a method
...
>>> Foo.bar.__func__.__get__(None, Foo)
>>> Foo.bar.__func__.__get__(Foo(), Foo)
>
这在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
>>> Foo.bar.__get__(None, Foo)
>>> Foo.bar.__get__(Foo(), Foo)
>
很好的答案,我从中学到了一些有趣的东西。
教程没有错。差异在9.3.4节方法对象的最后一段中解释。
@haccks:然而,这并没有使该行的声明正确。
这意味着你认为函数对象和方法对象没有区别?
@haccks:不,有很大的不同。
然后声明:但x.f与MyClass.f不同 - 它是一个方法对象,而不是一个函数对象。是的恕我直言。
@haccks:不,因为MyClass.f没有返回一个函数对象。它是一个方法对象,没有实例引用,因此它是未绑定的。
@haccks:type(x.f) is type(MyClass.f)是真的。 MyClass.f.__func__是实际的功能对象。
"通过打包(指向)实例对象和在抽象对象中一起找到的函数对象来创建方法对象:这是方法对象。":表示必须传递实例对象才能调用函数对象而在方法对象的情况下,由于它是通过打包(指向)实例对象(即self)和函数对象创建的,因此不需要实例对象作为参数。
@haccks:是的,这就是我在答案中解释的内容。你读过它吗?
我读了它,我认为该教程在相同的基础上区分了两个,这就是为什么我同意教程引用的行没有错。
@haccks:对不起,另一次讨论可能让我有点兴奋。教程中的行声明MyClass.f是一个函数,而实际上它也返回一个方法对象。这就是问题所在,这就是我的回答。不过,我不再确定你在问什么。无论教程中后面的内容是什么,一句话都是不正确的。
不需要激怒。我现在要离开这个讨论了。我之所以在2岁的帖子上讨论的原因只是因为这句话对我来说也是一个难题,最后我得出了这个答案。我已经对它进行了研究,我的意图是正确地做到这一点,不要与你争论并浪费你的时间。谢谢你的时间。
@haccks:不是问题。我不认为你被激怒了,我说我被一些无关紧要的东西所激怒,我在这里因为阅读我的答案而非常简短的评论让这种烦恼溢出来。抱歉!
不,我没有被激怒。我以为你很生气,这就是为什么我想退出:)