2010-10-03 3 views
2

Начиная с классом, как это:Как вызвать статический метод класса, используя имя метода и имя класса

class FooClass(object): 
    @staticmethod 
    def static_method(x): 
     print x 

нормально, я бы вызвать статический метод класса с:

FooClass.static_method('bar') 

Можно ли вызвать этот статический метод, имея только имя класса и имя метода?

class_name = 'FooClass' 
method_name = 'static_method' 
+1

Возможно? Да. Хорошая идея? Нет. Используйте только тогда, когда вам абсолютно необходимо. – delnan

+0

@ delnan, пожалуйста, не могли бы вы объяснить, почему? – systempuntoout

+1

По той же причине eval, exec, отражение в Java /.NET и аналогичные функции неодобрились: Потенциально сложнее отлаживать, более подвержены ошибкам и дырам в безопасности, медленнее и на вершине всего этого, это редко бывает проще или более изящным решением (совсем наоборот, часто сложнее добиться такого подхода чем делать это должным образом), не говоря уже о необходимости. – delnan

ответ

8

Вы не должны связываться с местными жителями(), как это предлагается в других ответах. Если у вас есть имя класса как строка и его нужно решить, используйте какой-либо реестр. Словарь будет работать нормально. Например.

class FooClass(object): 
    @staticmethod 
    def static_method(x): 
     print x 

registry = {'FooClass':FooClass} 

(я предполагаю, что вы хотите добавить еще много классов в этом реестре)

что поиск становится почти тривиальным:

getattr(registry['FooClass'], 'static_method')("bar") 
+0

+1 для наиболее разумного варианта. – delnan

+0

Согласовано. 'locals' и' globals' должны быть последним средством. +1. –

1

Если тип класса доступен из текущего модуля, вы можете получить доступ к классу в globals() Dict и метод с использованием getattr:

class FooClass(object): 
    @staticmethod 
    def static_method(x): 
     print x 

class_name = 'FooClass' 
method_name = 'static_method' 

getattr(globals()[class_name], method_name)("test") 
+0

с использованием globals() или locals() является ненужным взломом –

+0

@Ivo van der Wijk: Так что вы предлагаете вместо этого? – AndiDog

+0

@ Иво ван дер Вейк: Не видел вашего ответа. Вариант использования OP, очевидно, уже взломан, поэтому почему бы не использовать стандартные словари Python для доступа к классу? – AndiDog

2

Вот сырой путь:

>>> class FooClass(object): 
    @staticmethod 
    def static_method(x): 
     print x 


>>> class_name = 'FooClass' 
>>> method_name = 'static_method' 
>>> getattr(locals().get(class_name), method_name)("bar") 
bar 

Разбивка:

locals().get(class_name) 

Во-первых, найдите класс. В этом случае я использую locals(), поскольку я знаю, что класс доступен в локальном словаре. Это не удастся, если класс отсутствует в локальном словаре.

Далее, найдите метод класса.

getattr(locals().get(class_name), method_name) 

Используется getattr().

Наконец, вызовите метод.

getattr(locals().get(class_name), method_name)("bar") 
1

вы можете использовать getattr дважды. в первый раз на модуле, который содержит класс, а второй раз на самом

class_name = 'Foo' 
method_name = 'Bar' 

cls = getattr(mod, clsname) 
method = getattr(cls, method_name) 
method(args) 

класса Это не так гибко, как построение реестра (которые вы можете сделать с декоратором), но если вы не собираетесь сделайте это, чем это далеко лучшая альтернатива, чем возиться со стеком и стилистически, чище, чем возиться с sys.modules.

Обратите внимание, что модуль может import сам по себе без каких-либо побочных эффектов. поэтому классы не должны быть в другом модуле, чтобы это работало.

+0

Ваше замечание о том, как было бы лучше использовать 'getattr()' на объекте модуля, хорошо принято, потому что, скорее всего, он будет удобен в любом случае. Я попытался написать свой чуть более ранний ответ, чтобы он работал, делая как можно меньше предположений. – martineau

Смежные вопросы