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