调用Python静态方法对象

时间:2014-02-11 12:31:04

标签: python function object static-methods class-method

我希望这会奏效:

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以找出一些东西,但它是内置的。我希望它清楚我想在这里实现的目标。

你有什么想法怎么做得很好吗?我知道让这些@staticmethod全局解决问题,但这在我的模块中会很混乱。

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

2 个答案:

答案 0 :(得分:4)

Python具有 descriptor 对象的概念,它们是至少具有__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

因为以这种方式,bar也将通过描述符协议获取。但由于你有一个间接字典,你必须自己处理描述符__get__

检查http://docs.python.org/2/reference/datamodel.html#implementing-descriptors以获取更多信息。 (这就是classmethod,staticmethod装饰器所做的,因为你也想知道)。

答案 1 :(得分: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,
}

在完成类的构造之前引用类是很棘手的,因此在类定义结束后立即添加内容是最简单的。