jf...@ms4.hinet.net於 2018年12月28日星期五 UTC+8下午4時04分07秒寫道: > eryk sun at 2018/12/27 UTC+8 PM 6:58:33 wrote: > > On 12/27/18, jf...@ms4.hinet.net <jf...@ms4.hinet.net> wrote: > > > > > > I still don't get it. When I change it to using list comprehension, the > > > problem is still there. (it now has no late-binding variable, right? :-) > > > > > >>>> class Too: > > > ... XS = [15, 15, 15, 15] > > > ... Z4 = [val for val in XS] > > > ... Z5 = [XS[0] for val in XS] > > > ... > > > Traceback (most recent call last): > > > File "<stdin>", line 1, in <module> > > > File "<stdin>", line 4, in Too > > > File "<stdin>", line 4, in <listcomp> > > > NameError: name 'XS' is not defined > > > > > > The problem confuse me is that is XS a local variable of the list > > > comprehension? > > > > XS is not a local variable in the scope of either comprehension. XS is > > local to the class statement's scope. For each comprehension, an > > iterator for the current object referenced by XS gets instantiated > > (early binding) and passed as an argument to the comprehension scope. > > If we disassemble the comprehension code, we find that this iterator > > argument has the creatively illegal name ".0". (The bytecode > > references it by its fast-locals-array index, not its weird name.) > > > > In the Z5 case, XS is a non-local variable (late binding) in the > > loop-body expression (left-hand side) of the comprehension. That's > > common for Python code. In every iteration of the loop, the > > interpreter looks up the object referenced by the name "XS", which can > > change at any time (e.g. by another thread). > > In Python document 4.2.2. Resolution of names, the last paragraph: > > "...A class definition is an executable statement that may use and define > names. These references follow the normal rules for name resolution with an > exception that unbound local variables are looked up in the global namespace. > ...The scope of names defined in a class block is limited to the class block; > it does not extend to the code blocks of methods – this includes > comprehensions and generator expressions since they are implemented using a > function scope". > > These statements reflect the following difference: > > >>> xy = [1,2] > >>> [dir() for i in xy] > [['.0', 'i'], ['.0', 'i']] > >>> [xy[0] for i in xy] > [1, 1] > > >>> class foo(): > ... xs = [1,2] > ... z4 = [dir() for i in xs] > ... > >>> foo().z4 > [['.0', 'i'], ['.0', 'i']] > >>> class foo(): > ... xs = [1,2] > ... z4 = [xs[0] for i in xs] > ... > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "<stdin>", line 3, in foo > File "<stdin>", line 3, in <listcomp> > NameError: name 'xs' is not defined > >>> > > and it goes further: > > >>> [dir() for i in xy for j in xy] > [['.0', 'i', 'j'], ['.0', 'i', 'j'], ['.0', 'i', 'j'], ['.0', 'i', 'j']] > >>> class foo(): > ... xs = [1,2] > ... z5 = [dir() for i in xs for j in xs] > ... > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "<stdin>", line 3, in foo > File "<stdin>", line 3, in <listcomp> > NameError: name 'xs' is not defined > >>> > > That's all I had learn so far, although not understand the design decision > behind it yet:-( > > --Jach
Anyway, it "looks" weird. Isn't it? >>> xs = [5,6,7,8] >>> class foo(): ... xs = [1,2,3] ... z4 = [xs[i] for i in xs] ... >>> foo.z4 [6,7,8] xs in the "for" statement referenced to class variable xs and xs[i] in the body referenced to the global xs with i from locals. PS. Don't bother to reply. This is just for my own documentary:-) -- https://mail.python.org/mailman/listinfo/python-list