如何将类变量传递给参数化装饰器

时间:2018-10-05 06:43:34

标签: python python-decorators

我有一个带参数的装饰器。

def decorator(abc):
    def inner(func):
        def wrapper(*args, **kwargs):
            print(abc) # prints base class variable
            # do something
            return True
        return wrapper
    return inner

我有如下的儿童家长班:-

class ABC():

    abc = 1

    @decorator(abc)
    def func(self):
        return True


class DEF(ABC):

    abc = 2


obj = DEF()
print(obj.func())

我面临的问题是在将子类变量传递给装饰器时,它仍然需要基类变量。

如何将子类变量传递给装饰器?

3 个答案:

答案 0 :(得分:1)

在基类及其功能的定义时,将向您的装饰器传递一个具体值。没有任何属性访问,并且该函数也不会在派生类中进行神奇的重新定义和新值重新装修。 首先,将类属性传递给方法装饰器也没有多大意义,因为该方法无论如何都可以通过传递的实例动态访问它。您可以做的简单得多:

def decorator(func):
    def inner(self, *args, **kwargs):
        print(self.__class__.abc)  # actually prints the class attribute
        # do something
        return True
    return inner

class ABC(object):
    abc = 1

    @decorator
    def func(self):
        return True

>>> a = ABC()
>>> a.func()
1
True
>>> b = DEF()
>>> b.func()
2
True

答案 1 :(得分:0)

另一种解决方案可能是重写DEF中的方法,因为根据DEF .__ mro__,由于python无法找到DEF中声明的方法,它将进入父类并在那里找到它,并传入ABC的class属性。 / p>

DEF .__ mro__的输出:

(__main__.DEF, __main__.ABC, object)

建议的解决方案:

class ABC(object):
    abc = 1

    @decorator(abc)
    def func(self):
        return True

class DEF(ABC):
    abc = 2

    @decorator(abc)
    def func(self):
        return True

答案 2 :(得分:0)

一种简单的方法是考虑要在装饰器中处理的是属性的运行时值。然后,您只需传递属性名称并在运行时使用它即可。足够了,因为方法将其对象作为其第一个参数:

array(2) {
    ["type"]=> string(9) "ByteArray"
    ["value"]=> string(40) "0631901fb121f633fa496d3689649a06628f63c8"
}

给出预期的结果:

def decorator(attr):
    def inner(func):
        def wrapper(*args, **kwargs):
            print(getattr(args[0], attr)) # prints current attribute
            # do something
            return True
        return wrapper
    return inner

class ABC():

    abc = 1

    @decorator('abc')
    def func(self):
        return True

class DEF(ABC):

    abc = 2

obj = DEF()
obj.func()