python-使用_func调用实例方法__

python-使用_func调用实例方法__,python,Python,我是python新手,对Python2.7中的\uuu func\uu不太了解 我知道当我定义这样的类时: class Foo: def f(self, arg): print arg 我可以使用Foo().f('a')或Foo.f(Foo(),'a')调用此方法。但是,我不能通过Foo.f(Foo,'a')调用此方法。但我意外地发现,我可以使用Foo.f.\uu func.\uu(Foo,'a')甚至Foo.f.\uu func.\u1,'a')来获得相同的结果 我打

我是python新手,对Python2.7中的
\uuu func\uu
不太了解

我知道当我定义这样的类时:

class Foo:
    def f(self, arg):
        print arg
我可以使用
Foo().f('a')
Foo.f(Foo(),'a')
调用此方法。但是,我不能通过
Foo.f(Foo,'a')
调用此方法。但我意外地发现,我可以使用
Foo.f.\uu func.\uu(Foo,'a')
甚至
Foo.f.\uu func.\u1,'a')
来获得相同的结果


我打印出
Foo.f
Foo().f
Foo.f.\uuuu func\uuu
的值,它们都是不同的。然而,我的定义中只有一段代码。谁能帮助解释上述代码的实际工作原理,尤其是
\uuuu func\uuu
?我现在真的很困惑

当您访问
Foo.f
Foo().f
时,将返回一个方法;它在第一种情况下是未绑定的,在第二种情况下是绑定的。python方法本质上是一个围绕函数的包装器,该函数还包含对它所属类的引用。绑定时,它还保存对实例的引用

当您调用一个方法时,它将对传入的第一个参数进行类型检查,以确保它是一个实例(它必须是被引用类的实例或该类的子类)。当方法被绑定时,它将提供第一个参数,在未绑定的方法上,您自己提供它

这个方法对象具有
\uuu func\uu
属性,它只是对包装函数的引用。通过访问底层函数而不是调用该方法,可以删除类型检查,并且可以将任何需要的内容作为第一个参数传入。函数不关心它们的参数类型,但方法关心

注意,在Python3中,这已经改变了
Foo.f
只返回函数,而不是未绑定的方法
Foo().f
返回一个仍然、仍然绑定的方法,但无法再创建一个未绑定的方法

在引擎盖下,每个函数对象都有一个,这是返回方法对象的内容:

>>> class Foo(object):
...     def f(self): pass
... 
>>> Foo.f
<unbound method Foo.f>
>>> Foo().f
<bound method Foo.f of <__main__.Foo object at 0x11046bc10>>
>>> Foo.__dict__['f']
<function f at 0x110450230>
>>> Foo.f.__func__
<function f at 0x110450230>
>>> Foo.f.__func__.__get__(Foo(), Foo)
<bound method Foo.f of <__main__.Foo object at 0x11046bc50>>
>>> Foo.f.__func__.__get__(None, Foo)
<unbound method Foo.f>
>>类Foo(对象):
...     def f(自身):通过
... 
>>>富福
>>>Foo().f
>>>Foo.uuuu dict_uuuuu['f']
>>>Foo.f.uu func__
>>>Foo.f.uuuu func_uuuu.uuuu get_uuu(Foo(),Foo)
>>>Foo.f.uuu func.uuu get_uu(无,Foo)

这不是最有效的代码路径,因此,Python3.7添加了一个新的
LOAD\u方法
-
CALL\u方法
操作码对,它精确地替换了当前的
LOAD\u属性
-
CALL\u函数
操作码对,以避免每次都创建一个新的方法对象。此优化将
instance.foo()
的执行路径从
type(instance).\uu dict\uuu['foo'].\uu get\uuu(instance,type(instance))(
转换为
type(instance).\uu dict\uuuu['foo'](instance)
,因此将实例直接“手动”传递给函数对象。这将在现有的微基准上节省大约20%的时间。

请参阅。基本上,在Python2中,“绑定”和“未绑定”方法之间存在差异。感谢您的解释!我现在明白我的代码是如何工作的了。不过,我想我还需要一些时间来研究一下你刚才提到的
\uu get\uu
。你帮了大忙。