用另一个实例的方法装饰一个实例的方法

Posted

技术标签:

【中文标题】用另一个实例的方法装饰一个实例的方法【英文标题】:Decorating a method of an instance with a method from another instance 【发布时间】:2020-10-15 15:02:21 【问题描述】:

我对 Python 还很陌生。 我有 2 个类,每个类都有一个实例。 我想用另一个实例的方法来装饰其中一个实例的方法,例如:

import functools

class DecoClass():
    def __init__(self, deco_arg):
        self.deco_arg = deco_arg

    def my_decorator(self, f):
        @functools.wraps(f)
        def deco_wrapper(*args):
            print ('deco_wrapper argument :', self.deco_arg) # or just do something with deco_arg
            f = f(*args)
            return f
        return deco_wrapper

###

class MyClass():
    def __init__(self, arg, decorator):
            self.arg = arg
            self.decorator = decorator

    @self.decorator.my_decorator            # this is my problem, how can I do this ?
    def my_function(self):
        print ('my_function : ', self.arg)

###

if __name__ == "__main__":
a = DecoClass(1)
b = MyClass(10, a)
b.my_function()

上述方法当然不起作用,因为MyClass 不知道self.decorator 属性(在类级别)。可以这样做还是有其他方法?

PS。上面的例子过于简单化了。就我而言,DecoClass() 实际上将负责异常捕获、错误日志记录(到文件和/或 mysql)和其他各种事情。我只是想实例化一次,这样每次我想使用它时就不必传递参数(记录器、db auth 等)。此外,DecoClass() 将驻留在一个模块中,该模块将被不同的 Python 程序同时使用(每个实例都有自己的参数)。

感谢您的宝贵时间。

【问题讨论】:

除非您使用类变量而不是实例变量,否则您不能这样做。在这种情况下,你可能应该直接装饰它。 【参考方案1】:

这可能不能满足你的需求,但你可以试试这个:

import functools

class DecoClass():
    def __init__(self, deco_arg):
        self.deco_arg = deco_arg

    def my_decorator(self, f):
        @functools.wraps(f)
        def deco_wrapper(*args):
            print ('deco_wrapper argument :', self.deco_arg)
            r = f(*args)
            return r
        return deco_wrapper

###

a = DecoClass(1)
decorator = a.my_decorator

class MyClass():
    def __init__(self, arg):
            self.arg = arg
            self.decorator = decorator

    @decorator
    def my_function(self):
        print ('my_function : ', self.arg)

###

if __name__ == "__main__":
    b = MyClass(10)
    b.my_function()

【讨论】:

以上是关于用另一个实例的方法装饰一个实例的方法的主要内容,如果未能解决你的问题,请参考以下文章

用另一个类装饰一个python类方法

在另一个类中使用实例方法作为装饰器

蟒蛇 |实例化之前的类方法装饰器

Python的静态方法和类方法

使用类来写装饰器

classmethod和staticmethod区别