术语:用户定义的函数对象属性?

3
根据Python 2.7.12文档中用户自定义方法的描述:
用户自定义方法对象可以在获取类的属性时创建(可能通过该类的实例),如果该属性是用户自定义函数对象、未绑定的用户自定义方法对象或类方法对象。当属性是用户自定义方法对象时,仅当检索它的类与原始方法对象中存储的类相同或是其派生类时,才会创建新的方法对象;否则,原始方法对象将按原样使用。
我知道Python中的所有东西都是对象,所以“用户自定义方法”必须与“用户自定义方法对象”完全相同。然而,我不明白为什么会有“用户自定义函数对象属性”。例如,在以下代码中:
class Foo(object):
    def meth(self):
       pass

meth 是定义在类体内的函数,因此是一个方法。那么为什么我们可以有“用户定义的函数对象属性”?难道不是所有属性都在类体内定义吗?


奖励问题:提供一些示例,说明如何通过获取类的属性来创建用户定义的方法对象。难道不是在类定义中定义对象吗?(我知道方法可以分配给类实例,但那是猴子补丁。)
我请求帮助,因为这部分文档对我这个只懂C语言的程序员来说真的非常困惑,因为Python是一种支持函数式编程和面向对象编程的神奇语言,而我还没有掌握它。我已经做了很多搜索,但仍然无法弄清楚。

1
谢谢你的提问,我已经试着理解了一个小时。 - andnik
1个回答

7

当你执行时

class Foo(object):
    def meth(self):
       pass

你正在定义一个名为Foo的类,其中包含一个名为meth的方法。然而,当这个类定义被执行时,没有创建方法对象来表示该方法。 def语句只会创建普通的函数对象。
如果接下来执行:
Foo.meth

或者

Foo().meth

属性查找会找到函数对象,但是函数对象并不作为属性的值使用。相反,使用描述符协议,Python调用函数对象的__get__方法来构造一个方法对象,并且该方法对象被用作该查找的属性值。对于Foo.meth,方法对象是未绑定的方法对象,它的行为类似于您定义的函数,但具有额外的类型检查self。对于Foo().meth,方法对象是绑定的方法对象,它已经知道self是什么。
这就是为什么 Foo().meth() 不会抱怨缺少 self 参数的原因;你向方法对象传递0个参数,该对象随后将 self 添加到(空)参数列表的开头,并将参数传递给底层函数对象。如果 Foo().meth 直接求值为 meth 函数,你必须显式地传递 self 参数。
在Python 3中,Foo.meth 不会创建未绑定的方法对象;函数的 __get__ 仍然被调用,但它直接返回函数,因为 Guido 认为未绑定的方法对象没有用处。不过,Foo().meth 仍然会创建一个绑定的方法对象。

引文还说:“当属性是用户定义的方法对象时,……”但是一个类属性怎么可能是一个“用户定义的方法对象”,而不是一个“普通函数对象”呢? - nalzok
额外问题:您能提供一个例子来说明从中检索的类与原始方法对象中存储的类之间的区别吗? - nalzok
1
@sunqingyao:class Foo(object): def method(self): passclass Bar(object): method = Foo.method。现在Bar类的字典中有一个未绑定的方法对象,并且该未绑定的方法记录了它来自于Foo类。 - user2357112
如果 class Foo(object): def method(self): pass; method2 = Foo.method 是“从中检索的类与原始方法对象中存储的类相同”的情况,那么怎么办? - nalzok
@sunqingyao:接近了。在类语句体内,'Foo' 尚未存在,所以你需要在类语句完成后执行类似于 'Foo.method = Foo.method' 的操作。 - user2357112

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接