2015-04-15 10 views
0

Я хочу проксировать API через сеть. У меня есть API в словаре. Я хотел бы создать класс с помощью методов API из словаря, чтобы я мог использовать API так, как если бы был локальным. Проблема заключается в поиске имени моего динамически созданного метода. (Мой подход основан на Adding a Method to an Existing Object и Python dynamic class methods.)Найти имя динамического метода в Python

class MainClass(object): 
    def build_API(self): 
     methods = dict(meth1='arg1', meth2='arg2') 
     for key in methods.iterkeys(): 
      setattr(self, key, MethodType(self.default_API, self)) 
    def default_API(self, *args, **kwargs) 
     called_as_name = ???? 
     self.send_message(called_as_name, args, kwargs) 
    def send_message(self, called_as_name, *args, **kwargs) 
     ... 
     # Send API command over network 
     .... 

Чтобы использовать эту функцию:

api = MainClass() 
api.build_API() 
api.meth1() 

Однако, все, что я попробовать "called_as_name" всегда возвращает "default_API" и никогда "meth1". Как я могу получить «called_as_name = meth1» при вводе «api.meth1()» и «called_as_name = meth2» при вводе «api.meth2()»?

Я попытался:

curframe = inspect.currentframe() 
calframe = inspect.getouterframes(curframe, 2) 
called_as_name = calframe[1][3] 

из Python: How to get the caller's method name in the called method?

called_as_name = inspect.stack()[1][5] 

из Getting the caller function name inside another function in Python?

called_as_name = sys._getframe(1).f_code.co_name 

из Getting the caller function name inside another function in Python?

+0

Вам было бы лучше сделать 'meth1' и' meth2' неким поддельным вызываемым объектом, который сохранит свое имя. Кроме того, я действительно не думаю, что вы делаете, это хорошая идея. Все, что вы делаете, заключается в создании нескольких псевдонимов для одного метода ('default_API'). – BrenBarn

ответ

1

Попытка сделать это с помощью реальных методов и захватить имена из фрейма стека с помощью такого рода интроспективного обмана - это рецепт катастрофы. Вместо этого сделайте «методы» настраиваемыми вызываемыми объектами, которые знают их имена. Вот эскиз:

class FakeMethod(object): 
    def __init__(self, name, parent): 
     self.name = name 
     self.parent = parent 

    def __call__(self, *args, **kwargs): 
     self.parent.send_message(self.name, args, kwargs) 

class MainClass(object): 
    def build_API(self): 
     methods = dict(meth1='arg1', meth2='arg2') 
     for key in methods.iterkeys(): 
      setattr(self, key, FakeMethod(key, self)) 
    def send_message(self, called_as_name, *args, **kwargs): 
     print("Sending message:", called_as_name, args, kwargs) 

Тогда:

>>> api = MainClass() 
>>> api.build_API() 
>>> api.meth1() 
Sending message: meth1 ((), {}) {} 
>>> api.meth2() 
Sending message: meth2 ((), {}) {} 

В теории можно даже использовать __getattr__ на MainClass динамически генерировать FakeMethod каждый раз, когда имя атрибута доступ, который не определен, но перечисленные в некоторый список имен методов API.

+0

Отлично! Я думал, что мне нужно как-то сохранить имя с помощью функции, но не сделал прыжок, чтобы использовать объект класса. «__getattr__» - отличная идея, которую мне придется попробовать. – proximous