2014-02-11 30 views
2

我希望这会工作:调用Python的静态方法的对象

class A(object): 

    @classmethod 
    def do_it(cls, spam, eggs): 
     if spam in A.ways_to_do_it: 
      A.ways_to_do_it[spam](eggs) 
     super(A, cls).do_it(spam, eggs) 

    @staticmethod 
    def do_it_somehow(eggs): 
     ... 

    @staticmethod 
    def do_it_another_way(eggs): 
     ... 

    ways_to_do_it = { 
     'somehow': do_it_somehow, 
     'another_way': do_it_another_way, 
    } 

但它提出TypeError: 'staticmethod' object is not callable。我想检查staticmethod找出一些东西,但它是内置的。我希望这很清楚我想在这里实现什么。

你有什么想法如何很好地做到这一点?我知道制作这些全球化的解决方案可以解决这个问题,但这在我的模块中会很混乱。

P. S. do_it_somehowdo_it_another_way将仅从A.do_it被调用。

+1

对于那些试图将这个问题标记为重复的人:我认为这个问题比引用的问题更普遍 - 这是一个描述OP在这里的同样问题的角落案例。 – jsbueno

+0

@jsbueno:更一般的情况也包含在重复内容中。 –

回答

4

Python有一个概念描述符对象,这些对象至少具有方法__get__。这些对象行为不同于一个类或实例检索时,作为属性(其__get__方法被调用。)

@staticmethod装饰改造中具有静态方法的行为的描述符的后续函数声明 - 但说的行为会只有在以类属性检索对象时才可用。相反,上面的代码直接引用了对象。

既然是你还有其他(类)方法为你的字典的工作,你最好检索 所需yoiur方法类的创建,使每一个方法是通过描述协议检索:

class A(object): 

    @classmethod 
    def do_it(cls, spam, eggs): 
     if spam in A.ways_to_do_it: 
      A.ways_to_do_it[spam](eggs) 
     super(A, cls).do_it(spam, eggs) 

    @staticmetod 
    def do_it_somehow(eggs): 
     ... 

    @staticmetod 
    def do_it_another_way(eggs): 
     ... 

A.ways_to_do_it = { 
     'somehow': A.do_it_somehow, 
     'another_way': A.do_it_another_way, 
    } 

您可以在创建类之前检索静态方法,调用do_it_another_way.__get__(object, None) - 因为它不需要类引用(但需要一个有效的类作为第一个参数)。但是如果你希望你的字典也指向定义的类方法,那么它们肯定必须在创建类后被提取:在创建类之前,Python无法为你创建“绑定类方法”。

创建的类体内的类/静态方法等直接引用作品:

class A(object): 
    @staticmethod 
    def foo(): ... 

    bar = foo 

因为这样,酒吧也将通过描述协议获取。但既然你有一个间接字典,你必须照顾描述符__get__自己调用。

查看http://docs.python.org/2/reference/datamodel.html#implementing-descriptors了解更多信息。 (这是类方法,staticmethod装饰器所做的,因为你也想知道)。

+1

而在Python 3中,_all_(非内置)函数是描述符对象。 'A类:通过; a = lambda self:id(self);一个。a = a'将导致'a'成为类对象上的一个函数,任何实例上的绑定方法(甚至在该函数被设置为该类的属性之前创建的方法,假设它们已经不影响该函数) ,你甚至可以通过显式使用'__get__'来获得与JavaScript的'bind'相当的结果:'anA = A(); aa = a .__ get __(anA); AA()'。 – JAB

2

试试这样说:

class A(object): 

    @classmethod 
    def do_it(cls, spam, eggs): 
     if spam in A.ways_to_do_it: 
      A.ways_to_do_it[spam](eggs) 
     super(A, cls).do_it(spam, eggs) 

    @staticmethod 
    def do_it_somehow(eggs): 
     ... 

    @staticmethod 
    def do_it_another_way(eggs): 
     ... 

A.ways_to_do_it = { 
    'somehow': A.do_it_somehow, 
    'another_way': A.do_it_another_way, 
} 

它得到棘手你已经完成了类的施工前,所以这是最简单的类定义结束后有权东西添加到它引用的类。

+0

您的答案使其起作用,并描述了为什么它适用于classmethods的高级别。但静态方法不需要类引用,所以可以在类准备好之前引用它们。检查我的答案,看看发生了什么。 – jsbueno