指向Python中静态方法的指针 [英] Pointers to static methods in Python

查看:89
本文介绍了指向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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆