循环中定义的单元格变量

Cell variable defined in loop

当使用pylint检查我的代码时,我有W0640: Cell variable job defined in loop (cell-var-from-loop)

注意:请不要在阅读 item2 之前将其重复,大部分 post 与 item2 中的闭包或类似内容有关,我关心的是 item1 .

1.无法理解的是:执行是正确的,不像我接下来提到的item 2

a.py:

jobs = [1, 2]
for job in jobs:
    def fun():
        print(job)
    fun()

pylint:

$ pylint a.py
a.py:4:14: W0640: Cell variable job defined in loop (cell-var-from-loop)

执行:

$ python3 a.py
1
2

2.能理解的是下一段代码中的警告。 fun 中的 job 持有 for job in jobs 中的引用。然后fun并没有立即执行,所以当fun开始运行时,all_funcs中的两个fun都会持有外部job的引用,即 2。这可以在执行下一个代码时验证。

b.py:

all_funcs = []
jobs = [1, 2]
for job in jobs:
    def fun():
        return job
    all_funcs.append(fun)

for all_func in all_funcs:
    print(all_func())

pylint:

$ pylint b.py
b.py:5:15: W0640: Cell variable job defined in loop (cell-var-from-loop)

执行:

$ python3 b.py
2
2

3.能理解的是使用下一个代码来解决上面的问题,现在jobfun2 保留值。

c.py:

all_funcs = []
jobs = [1, 2]
for job in jobs:
    def fun2(job):
        def fun():
            return job
        return fun
    all_funcs.append(fun2(job))

for all_func in all_funcs:
    print(all_func())

pylint:

No W0640 warning.

执行:

$ python3 c.py
1
2

问题:

item2 一样,pylint 肯定会发现带有该警告的错误。所以我想知道尽管执行正确,但我是否可能错过 item1 中的任何潜在问题?

为了理解为什么 item 1 中的数据输出正确而 item 2 中的数据输出不正确,您可以检查屏幕上显示的变量地址

由于您是立即调用 fun(),变量 job 在 fun() 完全执行之前不会改变,因此您可以安全地忽略警告。

项目 1

jobs = [1, 2]
for job in jobs:
    def fun():
        print(hex(id(job)))
        print(job)
    fun()

输出:如您所见,地址不同

并且变量job在循环的每次迭代中指向不同的对象

0x1ee8cb400f0
1
0x1ee8cb40110
2

项目 2

由于延迟调用可执行对象导致意外结果

all_funcs = []
jobs = [1, 2]
for job in jobs:
    def fun():
        print(hex(id(job)))
        return job
    all_funcs.append(fun)

for all_func in all_funcs:
    print(all_func())

输出:不像item 1这里的地址是一样的

并且变量job在循环的每次迭代中指向同一个对象

0x1ee8cb40110
2
0x1ee8cb40110
2

如果我们稍微更改一下代码

all_funcs = []
jobs = [1, 2]
for job in jobs:
    def fun():
        print(hex(id(job)))
        return job
    all_funcs.append(fun)

job=5

for all_func in all_funcs:
    print(all_func())

产出

0x1ee8cb40170
5
0x1ee8cb40170
5

总结上面写的所有内容,pylint 警告您 可能 错误或 可能 出乎意料的结果,迫使你注意这段代码