使用 Python __call__魔术方法在类中复制“def”

use python __call__ magic method to replicate `def` within class

提问人:feiyang472 提问时间:4/17/2023 更新时间:4/18/2023 访问量:50

问:

假设我们有一个充当装饰器的类

class Foo:
    def __init__(self, func):
        self.func = func
        self.variable1 = 1
        self.variable2 = 2
    def __call__(self, *args, **kwargs):
        return self.func(*args, **kwargs)

它不能轻易地用于实例方法

class Bar:
    @Foo
    def dance(self):
        return 0
Bar().dance()  # TypeError: missing 1 required positional argument: 'self'

是否可以使行为像内置的 boundmethod,但也允许它具有其他变量,例如?dance()Bar().dance.variable1

一个相关的问题:我们知道未修饰的具有指向对象的属性。是否可以利用 in ?Bar().__dance____self__Bar__self__variable1

Python 函数式编程 闭包装饰 魔术方法

评论

0赞 Barmar 4/17/2023
如果要使用 in ,请使用 。selfvariable1@property
0赞 feiyang472 4/18/2023
@Barmar我想做一个对象的属性。正如 @chepner 所建议的,给你一个同时具有 (它是 ) 和 (这是 的属性) 的对象。我想依靠,而不是。variable1FooMethodType(Foo(dance))__self__Barvariable1Foovariable1__self__self

答:

2赞 chepner 4/18/2023 #1

Foo需要是一个描述符,其方法类似于 定义的方法。改编自 https://docs.python.org/3/howto/descriptor.html#functions-and-methods__get__function

class Foo:
    def __init__(self, func):
        self.func = func
        self.variable1 = 1
        self.variable2 = 2

    def __call__(self, *args, **kwargs):
        return self.func(*args, **kwargs)

    def __get__(self, obj, objtype):
        if obj is None:
            return self
        return types.MethodType(self, obj)

您提到的属性是 返回的值的属性,而不是 的属性。(这是因为计算结果不是函数,而是方法的返回值。__self__MethodType__get__danceBar().dancedance__get__

不使用类作为装饰器,而是使用函数(已经是描述符)可能更简单。

def Foo(f):
    def _(*args, **kwargs):
        return f(*args, **kwargs)
    return _