получить доступ к аргументам декоратора внутри функции-оболочки декораторов - PullRequest
2 голосов
/ 11 февраля 2011

Я безуспешно пытаюсь получить доступ к аргументам моих декораторов внутри функции-оболочки.

что у меня есть:

def my_decorator(arg1=False, arg2=None):

    def decorator(method):
        @functools.wraps(method)
        def wrapper(method, *args, **kwargs):
            # do something based on arg1 and arg2
            # accessing one of the two named arguments
            # ends up in a 'referenced before assignment'

            arg1 = arg1 # error
            arg2 = arg2 # error

            newarg1 = arg1 # working
            newarg2 = arg2 # working

            return method(*args, **kwargs)
        return wrapper
    return decorator

и я бы использовал его как обычный декоратор

@my_decorator(arg1=True, arg2='a sting or whatever else')
the_function()

Я действительно не понимаю, почему я не могу получить доступ к аргументам декораторов.

Ответы [ 2 ]

2 голосов
/ 11 февраля 2011

Вы можете получить доступ к arg1 и arg2, но вам не следует присваивать этим именам, даже с «расширенными» операторами присваивания, потому что это сделает их локальными переменными во внутренней функции. Полученное сообщение об ошибке показывает, что вы пытались сделать именно это (хотя вы не указали свой код).

В Python 3 вы можете обойти эту проблему, используя

nonlocal arg1, arg2

где-то в wrapper().

0 голосов
/ 11 февраля 2011

Это зависит от того, что вы делаете с arg1 и arg2. Как правило, крышки работают отлично без дополнительной работы. Однако, если вы переназначаете их во внутренней функции, Python предполагает, что это локальная переменная, и вы должны указать это иначе.

В Python 3 объявите nonlocal arg1, arg2. В Python 2 вы должны обмануть: оберните их в списки (arg1 = [arg1] во внешней функции) и используйте arg1[0] во внутренней функции. Если вы хотите объяснить, почему это работает, либо найдите вопросы по Python по этой теме, либо обратитесь к документации (где-то в справочнике по языку, я думаю, я буду искать).

Ваша проблема в том, что wrapper передает self на method. Там нет self. Вам придется принять это (и даже тогда вы ограничите декоратор методами - почему бы не позволить self проскользнуть в *args?).

Я не вижу, как вы читаете "ссылка перед присваиванием" из "глобального имени self не определено" ...

...