获取在 __call__ 内部调用的 python 3.x 方法的名称

Get the name of the python 3.x method that was called inside of __call__

我试图在 class 调用时添加一个方法。 例如:

class X(callable):
    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        method_called = self.get_method_name()

        if method_called not in self.__dict__:
            self.__dict__[method_called] = self.generic_function

        super().__call__(self, *args, **kwargs)

    def generic_function(self):
        print("I'm So Generic")

    def a(self):
        print('a')

    def get_method_name(self):
        #get the name of the method trying to be called
        method_name = ?????
        return method_name

def main():
    x = X()
    #should create a method nonexistant_method that acts like generic_function
    x.nonexistant_method()

main()

我意识到想要做这件事可能很奇怪,但它是我为某些研究构建的工具的一部分。这可能吗?或者也许有比 __call__?

更好的地方来完成这个

谢谢!

__call__ 用于调用对象本身时,如 x()x.nonexistant_method() (sic) 从不调用 x__call__ 方法;它会调用 nonexistant_method__call__(如果该方法存在)。

我想在这种情况下您想要的是 __getattr__。当访问不存在的属性时,将调用 __getattr__。在这种情况下,您只想 return 您的 generic_function.

def __getattr__(self, name):
    return self.generic_function

kindall 完全正确,您可能想要 __getattr__.

这是一个示例 class,它的工作方式与我认为您希望的工作方式相同:

class X:
    def make_missing_method(self, name):
        def missing_method(*args, **kwargs):
            print("Self object:", self)
            print("Method name:", name)
            print("Method args:", [args, kwargs])
        return missing_method

    def __getattr__(self, name):
        return self.make_missing_method(name)

这可能令人困惑,但它非常简单。

首先要注意,python 函数是对象,可以像其他任何东西一样传递。

我们在这里利用它,创建 make_missing_method,它只是一个函数 ,returns 是一个函数 。 (这被称为 closure)。

我们可以调用 X.make_missing_method('foo') 并验证这一点:

x = X()
f = x.make_missing_method('foo')
print(type(f))  # <class 'function'>

正如 kindall 所指出的,当您尝试访问不存在的实例属性时(使用 . 表示法),__getattr__ 会使用您尝试访问的名称作为参数。

我们可以将这两件事结合起来,创建一个 class 允许您在实例上调用以前未定义的方法,并使其按预期运行。

所以根据上面的class,我们可以写成:

x = X()
x.foo()

输出:

Self object: <__main__.X object at 0x00000000021E0BE0>
Method name: foo
Method args: [(), {}]

注意上面的Xclass中没有定义foo,但是missing_method还是被恰当地调用了。从 missing_method 内部,我们可以访问调用实例(通过 self)、尝试的方法名称(通过 name)和传递的参数。

要查看实际参数,您可以这样写:

x = X()
x.bar(1, 2, third="three")

输出:

Self object: <__main__.X object at 0x00000000021E0BE0>
Method name: bar
Method args: [(1, 2), {'third': 'three'}]

同样,bar 没有明确定义为方法,但调用 x.bar(...) 就像它是一样。