指向Python中静态方法的指针 [英] Pointers to static methods in Python
问题描述
为什么在下面的代码中,将类变量用作方法指针会导致未绑定的方法错误,而使用普通变量则可以正常工作:
Why is it that in the following code, using a class variable as a method pointer results in unbound method error, while using an ordinary variable works fine:
class Cmd:
cmd = None
@staticmethod
def cmdOne():
print 'cmd one'
@staticmethod
def cmdTwo():
print 'cmd two'
def main():
cmd = Cmd.cmdOne
cmd() # works fine
Cmd.cmd = Cmd.cmdOne
Cmd.cmd() # unbound error !!
if __name__=="__main__":
main()
完整错误:
TypeError: unbound method cmdOne() must be called with Cmd instance as
first argument (got nothing instead)
推荐答案
我喜欢从下至上查看这种行为.
I like to view this behaviour from the "bottom up".
Python中的函数充当"描述符对象".因此,它具有__get__()
方法.
A function in Python acts as a "descriptor object". As such, it has a __get__()
method.
对具有此类__get__()
方法的类属性的读取访问权被重定向"到该方法.对类的属性访问以attribute.__get__(None, containing_class)
执行,而对实例的属性访问则映射到attribute.__get__(instance, containing_class)
.
A read access to a class attribute which has such a __get__()
method is "redirected" to this method. A attribute access to the class is executed as attribute.__get__(None, containing_class)
, while an attribute access to the instance is mapped to attribute.__get__(instance, containing_class)
.
函数的__get__()
方法的任务是将该函数包装在一个方法对象中,该对象包装了self
参数-对于对实例的属性访问而言.这称为绑定方法.
A function's __get__()
method's task is to wrap the function in a method object which wraps away the self
parameter - for the case of an attribute access to the instance. This is called a bound method.
在2.x上的类属性访问中,函数的__get__()
返回一个未绑定的方法包装器,而正如我今天 ,在3.x上,它会返回自身. (请注意,__get__()
机制在3.x中仍然存在,但是函数只是返回自身.)如果您看一下它的调用方式,则几乎是相同的,但是未绑定的方法包装器还会检查正确的类型. self
参数.
On a class attribute access on 2.x, a function's __get__()
returns an unbound method wrapper, while, as I learned today, on 3.x, it returns itself. (Note that the __get__()
mechanism still exists in 3.x, but a function just returns itself.) That's nearly the same, if you look at how it is called, but an unbound method wrapper additionally checks for the correct type of the self
argument.
staticmethod()
调用仅创建一个对象,该对象的__get__()
调用旨在返回最初给定的对象,从而撤消了所描述的行为.这就是 HYRY的技巧的工作原理:属性acces撤消了staticmethod()
包装,调用再次进行了包装,以便"属性具有与旧属性相同的状态,尽管在这种情况下,staticmethod()
似乎被应用了两次(但实际上不是).
A staticmethod()
call just creates an object whose __get__()
call is designed to return the originally given object so that it undoes the described behaviour. That's how HYRY's trick works: the attribute acces undoes the staticmethod()
wrapping, the call does it again so that the "new" attribute has the same status as the old one, although in this case, staticmethod()
seems to be applied twice (but really isn't).
(顺便说一句:它甚至可以在这种怪异的环境中工作:
(BTW: It even works in this weird context:
s = staticmethod(8)
t = s.__get__(None, 2) # gives 8
尽管8
不是函数,而2
不是类.)
although 8
is not a function and 2
is not a class.)
在您的问题中,您有两种情况:
In your question, you have two situations:
cmd = Cmd.cmdOne
cmd() # works fine
访问该类并要求提供其cmdOne
属性(一个staticmethod()
对象).通过其__get__()
进行查询,并返回原始函数,然后调用该函数.这就是为什么它可以正常工作的原因.
accesses the class and asks for its cmdOne
attribute, a staticmethod()
object. This is queried via its __get__()
and returns the original function, which is then called. That's why it works fine.
Cmd.cmd = Cmd.cmdOne
Cmd.cmd() # unbound error
相同,但是随后将此功能分配给Cmd.cmd
.下一行是属性访问-再次对函数本身进行__get__()
调用,因此返回未绑定的方法,必须使用正确的self
对象作为第一个参数来调用该方法.
does the same, but then assigns this function to Cmd.cmd
. The next line is an attribute access - which does, again, the __get__()
call to the function itself and thus returns an unbound method, which must be called with a correct self
object as first argument.
这篇关于指向Python中静态方法的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!