【问题标题】:Find name of dynamic method in Python在 Python 中查找动态方法的名称
【发布时间】:2015-04-15 06:15:48
【问题描述】:

我想通过网络代理 API。我在字典中有 API。我想用字典中的 API 方法创建一个类,这样我就可以像在本地一样使用 API。麻烦在于找到我动态创建的方法的名称。 (我的方法是基于Adding a Method to an Existing ObjectPython 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”尝试的所有操作总是返回“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?

【问题讨论】:

  • 你最好把meth1meth2 做成某种虚假的可调用对象来存储自己的名字。另外,我真的不认为你在做什么是一个好主意。您所做的只是为单个方法创建一堆别名 (default_API)。

标签: python runtime introspection class-method


【解决方案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 ((), {}) {}

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

【讨论】:

  • 完美!我以为我需要以某种方式将名称与函数一起存储,但没有飞跃使用类对象。 “getattr”也是我必须尝试的好主意。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-21
  • 2019-08-17
  • 2010-10-29
  • 2012-12-01
相关资源
最近更新 更多