Pylint的Cell-var-from-loop警告

124

以下是代码:

for sort_key, order in query_data['sort']:
    results.sort(key=lambda k: get_from_dot_path(k, sort_key),
                 reverse=(order == -1))

Pylint报告了一个错误:

循环中定义的单元变量sort_key (cell-var-from-loop)。

有人能给个提示这是怎么回事吗?根据Pylint源代码的描述:

在闭包中使用的一个变量在循环中被定义。 这将导致所有闭包使用相同的值来关闭变量。

但我不知道它意味着什么。有人能给出问题的例子吗?


results 是什么类型的对象?普通列表吗?还是其他什么东西? - Kevin
1
请参见例如https://dev59.com/YWct5IYBdhLWcg3wAY3q。 - jonrsharpe
@Kevin 例如:results = [{key: value}, {key: value} ...] - xis
好的。在这种情况下,我同意chepner的观点,你不需要担心这个警告。 - Kevin
术语“闭包”在概念上可能会让人感到棘手,使我过度思考了这个错误,而 pylint 已经开始针对我的大量代码抛出此类错误。来自文档的示例代码清楚地说明了这是针对基本错误的简单检查:https://pylint.pycqa.org/en/latest/user_guide/messages/warning/cell-var-from-loop.html#:~:text=Cell%20variable%20%25s%20defined%20in,for%20the%20closed-over%20variable. 我将在 pylintrc 中禁用它。 - Ben Quigley
2个回答

138

函数体内的 lambda 中的名称 sort_key 在实际调用函数时被查找,因此它将看到最近的值sort_key。由于您立即调用了sort,在使用生成的函数对象之前,sort_key 的值不会改变,因此您可以安全地忽略该警告。要消除警告,您可以将sort_key作为参数的默认值添加到lambda中:

results.sort(key=lambda k, sk=sort_key: get_from_dot_path(k, sk),
             reverse=(order == -1))

14
如果出现警告,我会更倾向于修复问题而非忽略它。如果可能的话,我会使用key=partial(get_from_dot_path, foo=sort_key)代替lambda表达式(假设get_from_dot_path定义了一些名为foo的参数名,可以将其用作关键字参数;partial仅允许从左侧填充位置参数)。 - chepner
1
啊,我没想到这样做会解决问题,我以为它们是等价的;既然如此,我同意。 - Tim Diels
3
请注意,目前这个技巧并不总是有效。链接 https://github.com/PyCQA/pylint/issues/3107 - Daniel Pinyol
1
使用nonlocal没有起到作用,我不得不像@chepner建议的那样使用partial() - Jens
谢谢。我遇到了类似的问题"filtered_events = list(filter(lambda x, _phase_no=phase_no: 'phase_no' in x and x['phase_no'] == _phase_no, events))",在这里,phase_no 对我造成了问题。 - Dinesh P B
这篇帖子现在已经与Pylint文档链接起来了 :) 但是我认为如果k没有直接使用,就不能直接使用partial技巧。例如,get_from_dot_path(2*k, sort_key)无法直接转换为partial - Abhijit Sarkar

12

使用functools.partial()函数:

import functools
results.sort(key=functools.partial(get_from_dot_path, foo=sort_key),
             reverse=(order == -1))

1
可以确认这不仅消除了警告,而且真正解决了问题。例如尝试创建一个lambda列表并打印范围1,10 - 使用lambda,它们都会打印9,但使用functools.partial它们会打印每个值。 - TamaMcGlinn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接