让我们考虑一下下面的例子。
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
方法。为什么会出现这种情况?这段代码以这种方式实现是不是一个好主意?如果是--有什么替代方案吗?
简答。 这是Pylint 2.4.4(和更老版本)的一个bug。我已经提交了一个补丁幽林特的下一个版本中会收录该作品,该作品已被合并到母版中。
详见 (对于好奇的人来说)。
当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错误地将装饰符视为函数内部的装饰符,因此在函数作用域而不是类作用域。
解决方法:
作为一个静态代码检查器,Pylint只能走到这一步。它目前有500个未解决的问题,所以预计会有一些误报。目前,你可以遵循 @chepner'的建议,禁用Pylint警告, 只是为了这一行。
@dec([i + 5 for i in x]) # pylint: disable=undefined-variable
但我现在就要! (对于那些想在不作弊的情况下获得1010代码等级的人)
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
抱怨(尽管它会给出一些风格警告)。如果有变化,请重新打开bug报告!