python - 方法的装饰器参数不能是基于类的静态成员的列表理解

标签 python oop decorator pylint

让我们考虑以下示例:

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 在 g 的装饰器参数中提示 undefined-variable x 方法。为什么会这样?这段代码不是以这种方式实现的好主意吗?如果是这样 - 还有其他选择吗?

最佳答案

简短回答:这是 Pylint 2.4.4(及更早版本)中的错误。 I've submitted a patch , 已经合并到 master 中,将包含在 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_listreturns 注释。这导致 Pylint 错误地将装饰器视为在函数内部,因此在函数范围而不是类范围内。

解决方法:

作为静态代码检查器,Pylint 也只能到此为止了。它目前有 500 个 Unresolved 问题,所以预计会有一些误报。现在可以关注@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 投诉(尽管它会给出一些样式警告).如果这有任何变化,请重新打开错误报告!

关于python - 方法的装饰器参数不能是基于类的静态成员的列表理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61271870/

相关文章:

python - Django manage.py 未知命令 : 'syncdb'

python - 如何从 python 脚本使用 PCRE 正则表达式?

python - 如何创建 "list"类的子类,它在实例化时自行排序?

python - Django 教程第 3 部分 - NoReverseMatch at/polls/

java - Pattern 避免重复处理 Block

带有 __ 的 Python 'hide' 方法

c++ - 设计可定制的字符串过滤器

python - 字典作为类中的局部变量

python - 类级装饰器

python - 类装饰器禁用 __init_subclass__