fou*_*ver 8 python class python-3.x functools
我正在阅读有关函数在设置为类 atrributes 时如何成为绑定方法的内容。然后我观察到,对于 . 包装的函数来说情况并非如此functools.partial
。对此有何解释?
简单的例子:
from functools import partial
def func1():
print("foo")
func1_partial = partial(func1)
class A:
f = func1
g = func1_partial
a = A()
a.f() # TypeError: func1() takes 0 positional arguments but 1 was given
a.g() # prints "foo"
Run Code Online (Sandbox Code Playgroud)
我有点期望他们都会有同样的行为方式。
允许函数成为绑定方法的技巧就是__get__
魔术方法。
非常简单地总结一下该页面,当您访问实例上的字段(例如 )时,foo.bar
Python 首先检查'sbar
中是否存在(或者,如果有的话)。如果确实如此,我们会将其退回,不会造成任何伤害。如果没有,那我们就拭目以待吧。然而,当我们通过实例访问类上的字段时,神奇的事情发生了。当我们写 时,假设没有on的(resp. ),那么我们实际上调用foo
__dict__
__slots__
type(foo)
Foo.bar
Foo
foo.bar
bar
foo
__dict__
__slots__
Foo.bar.__get__(foo, Foo)
. 也就是说,Python 调用一个魔术方法来询问对象希望如何检索它。
这就是属性的实现方式,也是绑定方法的实现方式。在深处的某个地方(可能是用 C 语言编写的),类型__get__
上有一个函数,当通过实例访问时,该函数会绑定该方法。 function
functools.partial
尽管看起来很像函数,但它并不是类型 的实例function
。它只是一个随机的类,碰巧实现了__call__
,并且没有实现__get__
。为什么不呢?好吧,他们可能只是认为这不值得,或者可能根本没有人考虑过。无论如何,“绑定方法”技巧适用于调用的类型function
,而不是所有可调用对象。
关于魔术方法的另一个有用资源,特别__get__
是:https://rszalski.github.io/magicmethods/#descriptor
该类型function
实现了该__get__
方法:
>>> import types
>>> types.FunctionType.__get__
<slot wrapper '__get__' of 'function' objects>
Run Code Online (Sandbox Code Playgroud)
partial
才不是。
>>> from functools import partial
>>> partial.__get__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'functools.partial' has no attribute '__get__'. Did you mean: '__ge__'?
Run Code Online (Sandbox Code Playgroud)
该__get__
方法使a.f
评估结果为 type 的值method
而不是A.f
. 没有__get__
,a.g
相当于A.g
。