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. (Это то, что делают classmethod, декораторы статических методов, так как вы также хотели узнать).
Что касается тех, кто пытается отметить этот вопрос как дубликат: я думаю, что этот вопрос является более общим случаем, чем упоминаемый, - это угловой случай, изображающий ту же проблему, что и у ОП. – jsbueno
@jsbueno: более общий случай также рассматривается в дубликатах. –