Доступ к свойству класса в качестве аргумента декоратора - PullRequest
1 голос
/ 29 марта 2020

Я пытаюсь применить условный декоратор , как описано в другом сообщении stackoverflow, но я бы хотел, чтобы условие было установлено внутри класса, в котором он используется. Вместо этого я получаю ошибку Reference, указывающую, что self не определено.

class foo:
    def __init__(self):
        self.debug = True

    @conditional_decorator(decorator, self.debug)
    def function(self):
        pass

Я попытался определить глобальную переменную и обновить ее из метода __ init __ () , но он сохранил свое первоначальное значение при вызове в качестве аргумента декоратора.

debug = None

class foo:
    def __init__(self):
        self.debug = True
        global debug
        debug = self.debug

    @conditional_decorator(decorator, debug)
    def function(self):
        pass

Единственный способ, которым она работала, - объявление глобальной переменной и установка ее вне класса.

Как я могу применить значение свойства класса для декоратора?

Ответы [ 3 ]

2 голосов
/ 29 марта 2020

Вот как вы делаете декоратор для обработки классов и аргументов:

from functools import wraps


def conditional_decorator(param):
    def real_decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kw):
            cls = args[0]
            print(cls.debug)
            print(param)
        return wrapper
    return real_decorator


class foo:
    def __init__(self):
        self.debug = True

    @conditional_decorator('param1')
    def function(self):
        pass



f = foo()
f.function()

Вывод:

True
param1
1 голос
/ 29 марта 2020

Обновление ответа, данного @Maurice Meyer, которое позволяет номинировать члена класса:

from functools import wraps

def conditional_decorator(decoration, member):
    def decorator(method):
        predecorated = decoration(method)
        @wraps(method)
        def wrapper(*args, **kwargs):
            self = args[0]
            condition = getattr(self, member)
            if not condition:
                return method(*args, **kwargs)
            return predecorated(*args, **kwargs)
         return wrapper
    return decorator

#And used like this for example:
class foo:
    def __init__(self, debug):
        self.debug = debug

    @conditional_decorator(decorator, "debug")
    def function(self):
        pass

f1 = foo(True)
f1.function()
0 голосов
/ 29 марта 2020

Декоратор не должен быть условным. Скорее, когда вызывается декорированная функция, она должна посмотреть на self.debug, чтобы определить, использовать ли оригинальную функцию или обернутую часть.

def conditional_decorator(dec):
    def decorator(func):
        def _(self, *args, **kwargs):
            f = func
            if self.debug:
                f = dec(f)
            return f(self, *args, **kwargs)
        return _
    return decorator


def decorator(f):
    def _(*args, **kwargs):
        print("Decorated")
        return f(*args, **kwargs)
    return _


class foo:
    def __init__(self, debug):
        self.debug = debug

    @conditional_decorator(decorator)
    def function(self):
        print("foo stuff")

foo(True).function()
print("===")
foo(False).function()

выводит

Decorated
foo stuff
===
foo stuff
...