【问题标题】:Using class as decorator for another class's method使用类作为另一个类方法的装饰器
【发布时间】:2018-08-15 00:20:18
【问题描述】:

我在使用一个类来装饰另一个类的方法时遇到问题。代码如下:

class decorator(object):
    def __init__(self, func):
        self.func = func

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

class test(object):
    @decorator
    def func(self, x, y):
        print x, y

t = test()
t.func(1, 2)

显示这个错误

TypeError: func() takes exactly 3 arguments (2 given).

如果调用使用:

t.func(t, 1, 2)

然后它通过了。但是如果装饰器被拿走,那么这条线就会再次出现问题。

为什么会发生这种情况以及如何解决?

编辑:decorator.__call__ 中显示自我的第二版代码应该与test.func 中的自我不同:

class decorator(object):
    def __init__(self, func):
        self.func = func

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

class test(object):
    def __init__(self):
        self.x = 1
        self.y = 2
    @decorator
    def func(self):
        print self
        print self.x, self.y

t = test()
t.func()

这显示了同样的错误。但是

t.func(t)

有效但不理想。

【问题讨论】:

    标签: python class methods decorator


    【解决方案1】:

    要作为方法工作,类中的对象需要实现the descriptor protocol 的一部分。也就是说,它应该有一个 __get__ 方法,该方法返回一个可调用对象,该对象已“绑定”到查找该方法的实例。

    这是一种可以使用包装函数的方法:

    class decorator(object):
        def __init__(self, func):
            self.func = func
    
        def __get__(self, instance, owner):
            def wrapper(*args):
                return self.func(instance, *args) # note, self here is the descriptor object
            return wrapper
    

    您可以改为从__get__ 返回某个其他类的实例,而不是一个函数,并使用该其他类的__call__ 方法来实现包装器。但是,如果您不使用闭包,则需要将 instance 显式传递给包装类(以及函数,因为 self.func 在描述符类之外不起作用)。

    【讨论】:

    猜你喜欢
    • 2021-10-23
    • 1970-01-01
    • 2018-11-11
    • 2021-12-26
    • 2021-04-20
    • 2016-10-14
    • 2014-02-18
    • 1970-01-01
    • 2014-01-14
    相关资源
    最近更新 更多