class MyClass: pass
def myfunction(): print('hi')
MyClass.foo = myfunction
obj = MyClass()
obj.foo = myfunction
MyClass.foo()
obj.foo()
字符串
我正在学习Python,无法理解最后两行是如何工作的,而不会出现任何矛盾的错误。我先用class对象赋值和调用同一个myfunction,然后用instance对象赋值和调用,我所理解的是,当用instance对象调用一个方法时,python隐式地将示例传递给方法。因此,我希望最后两行中的一行能正常工作,但不是两行都能正常工作。糊涂了
1条答案
按热度按时间mkh04yzy1#
作为第一个近似,当你写
字符串
Python尝试通过以下方式查找
foo
:1.检查
obj
是否具有名为foo
的属性,然后1.检查
obj
的类(obj.__class__
,这里是MyClass
)是否具有属性foo
。如果在第一步中,找到了一个名为
foo
的属性,那么该对象将被返回。无论该对象是 * 什么 (无论是函数对象还是其他对象),它都会被返回。这就是代码中发生的情况:obj
有一个名为foo
的属性,因此该对象将被返回-MyClass.foo
永远不会被考虑。如果
obj
没有属性foo
,那么我们进入第二步。在这里,一些特殊的行为开始了:Descriptor Protocol。如果obj.__class__
有一个名为foo
的属性,那么在返回该对象之前,Python首先检查foo
是否是描述符。如果是,那么不是返回foo
,Python将返回foo.__get__(obj)
。 这 * 是方法的工作方式。方法只是通过描述符协议访问的类的函数属性。如果你只写
型
那么你就有问题了。现在,
obj
* 没有 * 一个名为foo
的属性,所以访问obj.foo
在MyClass
上查找foo
。MyClass
确实有一个名为foo
的属性,它绑定到myfunction
。myfunction
,像所有函数对象一样,是一个描述符,所以Python调用myfunction.__get__(obj)
,它返回一个绑定方法对象。这个绑定方法对象是一个可调用对象,当它被调用时,它会尝试将obj
传递给myfunction
。由于myfunction
不接受任何参数,这将产生一个错误,正如你最初怀疑的那样:型
1完整的属性查找过程要复杂得多。请参见3.3.2.从Python数据模型文档中自定义属性访问以了解更大的情况。