在 Python 中查找动态方法的名称

Find name of dynamic method in Python

我想通过网络代理 API。我在字典中有 API。我想用字典中的 API 方法创建一个 class,这样我就可以像在本地一样使用 API。问题是找到我动态创建的方法的名称。 (我的方法是基于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
        ....

要使用这个:

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

然而,我为 "called_as_name" 尝试的一切总是 returns "default_API" 而从来没有 "meth1"。我如何在输入 "api.meth1()" 时得到 "called_as_name = meth1" 和在输入 "api.meth2()" 时得到 "called_as_name = 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?

尝试使用实际方法来执行此操作并使用那种自省技巧从堆栈帧中获取名称是灾难的根源。相反,使 "methods" 成为知道其名称的自定义可调用对象。这是一个草图:

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 ((), {}) {}

理论上,您甚至可以在 MainClass 上使用 __getattr__ 来在每次访问未定义但列在某些 API 方法名称列表中的属性名称时动态生成 FakeMethod。