Параметр декоратора метода не может быть списком, основанным на члене класса 'stati c - PullRequest
3 голосов
/ 17 апреля 2020

Давайте рассмотрим следующий пример:

def dec(arg):
    def wrapper(m):
        def result(self):
            print(arg)
            m(self)
        return result
    return wrapper


class X:

    x = [7]

    @dec(x)
    def f(self):
        print('hello from f')

    @dec([i + 5 for i in x])
    def g(self):
        print('hello from g')


X().f()
X().g()

Код работает нормально при моей установке python3.6, но Pylint жалуется на undefined-variable x в параметре декоратора метода g. Почему это случилось? Разве этот код не является хорошей идеей для реализации таким образом? Если да - какие альтернативы?

1 Ответ

3 голосов
/ 25 апреля 2020

Краткий ответ: Это ошибка в Pylint 2.4.4 (и старше). Я представил патч , который был объединен с мастером и будет включен в следующую версию Pylint.

Подробности (для любопытных):

Когда Python анализирует код в абстрактном синтаксическом дереве (AST) узлы, узлы декоратора (например, @dec...) присоединяются к decorator_list узла для определения функции (например, def g...):

    stmt = FunctionDef(identifier name, arguments args,
                       stmt* body, expr* decorator_list, expr? returns,
                       string? type_comment)

У Pylint был специальный случай для аргументов функции (args), но он забыл проверить аннотации decorator_list и returns. Это приводило к тому, что Pylint неправильно обрабатывал декораторы, как если бы они находились внутри функции, и, следовательно, в области действия функции, а не в области действия класса.

Обходной путь :

Как состояние c код проверки, Pylint может только go пока. В настоящее время у него 500 открытых выпусков, поэтому ожидайте несколько ложных срабатываний Пока вы можете следовать предложению @ chepner , чтобы отключить предупреждение Pylint, только для этой строки:

    @dec([i + 5 for i in x]) # pylint: disable=undefined-variable

Но я хочу это сейчас! ( для тех, кому нужна оценка кода 10/10 без читерства)

git clone https://github.com/PyCQA/astroid.git
git clone https://github.com/PyCQA/pylint.git
pip install ./astroid/
pip install ./pylint/
pylint --version

pylint 2.5.0-dev1 astroid 2.4.0

С разработанной версией Pylint (и Astroid, библиотека Pylint использует для синтаксического анализа), код в вопросе не должен давать никаких жалоб undefined-variable (хотя это даст некоторые стилистические предупреждения). Если это когда-нибудь изменится, пожалуйста, откройте отчет об ошибке!

...