Find name of dynamic method in Python

半腔热情 提交于 2019-12-25 05:58:05

问题


I want to proxy an API over a network. I have the API in a dictionary. I'd like to create a class with the API methods from the dictionary so I can use the API as if I was local. The trouble is finding the name of my dynamically created method. (My approach is based on Adding a Method to an Existing Object and Python dynamic class methods.)

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
        ....

To use this:

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

However, everything I try for "called_as_name" always returns "default_API" and never "meth1". How can I get "called_as_name = meth1" when I type "api.meth1()" and "called_as_name = meth2" when I type "api.meth2()"?

I have tried:

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

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

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

from Getting the caller function name inside another function in Python?

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

from Getting the caller function name inside another function in Python?


回答1:


Trying to do this with actual methods and grabbing the names from the stack frame with that sort of introspection trickery is a recipe for disaster. Instead, make the "methods" be custom callable objects that know their names. Here's a sketch:

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)

Then:

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

In theory you could even use __getattr__ on the MainClass to dynamically generate a FakeMethod every time an attribute name is accessed that is not defined but is listed in some list of API method names.



来源:https://stackoverflow.com/questions/29642822/find-name-of-dynamic-method-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!