关于运行时:在Python中查找动态方法的名称

Find name of dynamic method in Python

我想通过网络代理API。 我在字典中有API。 我想用字典中的API方法创建一个类,这样我就可以像使用本地一样使用API。 麻烦的是找到我动态创建的方法的名称。 (我的方法基于向现有对象添加方法和Python动态类方法。)

1
2
3
4
5
6
7
8
9
10
11
12
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
        ....

要使用它:

1
2
3
api = MainClass()
api.build_API()
api.meth1()

但是,我为"called_as_name"尝试的所有内容始终返回"default_API"而从不返回"meth1"。 当我输入"api.meth2()"时输入"api.meth1()"和"called_as_name = meth2"时,如何获得"called_as_name = meth1"?

我试过了:

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

来自Python:如何在被调用方法中获取调用者的方法名称?

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

从获取Python中另一个函数内的调用函数名称?

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

从获取Python中另一个函数内的调用函数名称?


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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)

然后:

1
2
3
4
5
6
>>> api = MainClass()
>>> api.build_API()
>>> api.meth1()
Sending message: meth1 ((), {}) {}
>>> api.meth2()
Sending message: meth2 ((), {}) {}

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