Home > Mobile >  Cell variable defined in loop
Cell variable defined in loop

Time:12-29

When use pylint to check my code, I have W0640: Cell variable job defined in loop (cell-var-from-loop).

NOTE: Please don't make it as duplicate before you read item2, most of the post is related to the closure or something like in the item2, my concern is on item1.

1. What can't understand is: the execution is correct unlike the item 2 I mentioned next.

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)

execution:

$ python3 a.py
1
2

2. What I can understand is the warning in next code. The job in fun hold a reference of the one in for job in jobs. Then fun not executed at once, so when the fun starts run, both fun in all_funcs will hold the reference of outer job, that is 2. This could be verified when execute next code.

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)

execution:

$ python3 b.py
2
2

3. What I can understand is to use next code to fix above issue which now the job in the fun2 holds the value.

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.

execution:

$ python3 c.py
1
2

Question:

As in item2, pylint definitely find a bug with that warning. So I wonder if possible I missed any potential issue in item1 although the execution is correct?

CodePudding user response:

In order to understand why the data output in item 1 is correct and in item 2 it is not, you can check the addresses of the variables that are displayed on the screen

Since you are calling fun() immediately, the variable job will not change before the fun() complete execution , so you can safely ignore the warning.

item 1

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

output: as you can see the addresses are different

and the variable job points to different objects with each iteration of the loop

0x1ee8cb400f0
1
0x1ee8cb40110
2

item 2

Unexpected result due to delayed call of executable object

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())

output: unlike item 1 here the addresses are the same

and the variable job points to the same object with each iteration of the loop

0x1ee8cb40110
2
0x1ee8cb40110
2

also if we change the code a little

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())

output

0x1ee8cb40170
5
0x1ee8cb40170
5
  • Related