我希望这会起作用:
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_somehow
和 do_it_another_way
将仅从 A.do_it
调用。
Python 有一个描述符 对象的概念,这些对象至少具有__get__
方法。当从类或实例中检索这些对象作为属性(调用它们的 __get__
方法)时,这些对象的行为不同。
@staticmethod
装饰器将后续函数声明转换为具有静态方法行为的描述符 - 但所述行为仅在将对象作为类属性检索时可用。相反,上面的代码直接引用了对象。
既然你还有其他(类)方法让你的字典工作,你最好
在创建类后检索您想要的方法,以便通过描述符协议(protocol)检索每个方法:
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 不可能在类创建之前为你创建一个“绑定(bind)类方法”。
在类体内创建对类/静态方法的其他直接引用:
class A(object):
@staticmethod
def foo(): ...
bar = foo
因为这样的话,bar也会通过描述符协议(protocol)来获取。但是因为你有一个间接字典,你必须照顾描述符 __get__
调用你自己。
检查 http://docs.python.org/2/reference/datamodel.html#implementing-descriptors了解更多信息。 (这就是类方法、静态方法装饰器所做的,因为您也想知道)。