According to PEP 572, section Scope of the target, the following examples of assignment expressions should be invalid and raise TargetScopeError
.
[i := i+1 for i in range(5)]
Python 3.8.0a1 (tags/v3.8.0a1:e75eeb00b5, Feb 3 2019, 20:47:39) [MSC v.1916 64 bit (AMD64)] on win32
>>> test = [i := i+1 for i in range(5)]
>>> i
5
>>> test
[1, 2, 3, 4, 5]
>>>
No error here. Works as expected, equivalent to
>>> test = []
>>> for i in range(5):
... i = i + 1
... test.append(i)
...
>>> i
5
>>> test
[1, 2, 3, 4, 5]
>>>
[[(j := j) for i in range(5)] for j in range(5)]
Python 3.8.0a1 (tags/v3.8.0a1:e75eeb00b5, Feb 3 2019, 20:47:39) [MSC v.1916 64 bit (AMD64)] on win32
>>> test = [[(j := j) for i in range(5)] for j in range(5)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
File "<stdin>", line 1, in <listcomp>
NameError: name 'j' is not defined
>>>
I don't understand this error. This listcomp should be equivalent to
>>> test = []
>>> for j in range(5):
... sublist = []
... for i in range(5):
... j = j
... sublist.append(j)
... test.append(sublist)
...
>>> j
4
>>> test
[[0, 0, 0, 0, 0], [1, 1, 1, 1, 1], [2, 2, 2, 2, 2], [3, 3, 3, 3, 3], [4, 4, 4, 4, 4]]
>>>
Or, according to PEP 572, Appendix B, equivalent to
>>> def f():
... if False:
... j = None
... def outer_generator(outer_iterator):
... nonlocal j
... def inner_generator(inner_iterator):
... nonlocal j
... for i in inner_iterator:
... j = j
... yield j
... for j in outer_iterator:
... yield list(inner_generator(range(5)))
... test = list(outer_generator(range(5)))
... print(j)
... print(test)
...
>>> f()
4
[[0, 0, 0, 0, 0], [1, 1, 1, 1, 1], [2, 2, 2, 2, 2], [3, 3, 3, 3, 3], [4, 4, 4, 4, 4]]
>>>
[i := 0 for i, j in stuff]
Python 3.8.0a1 (tags/v3.8.0a1:e75eeb00b5, Feb 3 2019, 20:47:39) [MSC v.1916 64 bit (AMD64)] on win32
>>> stuff = [(11, 22), (33, 44)]
>>> test = [i := 0 for i, j in stuff]
>>> i
0
>>> test
[0, 0]
>>>
No error here. Works as expected, equivalent to
>>> stuff = [(11, 22), (33, 44)]
>>> test = []
>>> for i, j in stuff:
... i = 0
... test.append(i)
...
>>> i
0
>>> test
[0, 0]
>>>
[i+1 for i in i := stuff]
Python 3.8.0a1 (tags/v3.8.0a1:e75eeb00b5, Feb 3 2019, 20:47:39) [MSC v.1916 64 bit (AMD64)] on win32
>>> stuff = [11, 22, 33, 44]
>>> test = [i+1 for i in i := stuff]
File "<stdin>", line 1
test = [i+1 for i in i := stuff]
^
SyntaxError: invalid syntax
>>> test = [i+1 for i in (i := stuff)]
>>> i
[11, 22, 33, 44]
>>> test
[12, 23, 34, 45]
>>>
Obvious syntax error (in
has higher priority than :=
). After adding parentheses, the listcomp works as expected, equivalent to
>>> stuff = [11, 22, 33, 44]
>>> test = []
>>> i = stuff
>>> for i in i:
... test.append(i+1)
...
>>> i
44
>>> test
[12, 23, 34, 45]
>>>
(except that in the latter case, the loop target i
is not hidden in an implicit inner scope)
The above tested behavior is the same in version 3.8.0a2.
The above tested behavior is the same in version 3.8.0a3.
The above tested behavior is the same in version 3.8.0a4.
The above tested behavior is the same in version 3.8.0b1.
The above tested behavior is the same in version 3.8.0b2.
The above tested behavior is the same in version 3.8.0b3.
The above tested behavior changed in version 3.8.0b4. All the example comprehensions now raise SyntaxError:
Python 3.8.0b4 (tags/v3.8.0b4:d93605d, Aug 29 2019, 23:21:28) [MSC v.1916 64 bit (AMD64)] on win32
>>> test = [i := i+1 for i in range(5)]
File "<stdin>", line 1
SyntaxError: assignment expression cannot rebind comprehension iteration variable 'i'
>>>
Python 3.8.0b4 (tags/v3.8.0b4:d93605d, Aug 29 2019, 23:21:28) [MSC v.1916 64 bit (AMD64)] on win32
>>> test = [[(j := j) for i in range(5)] for j in range(5)]
File "<stdin>", line 1
SyntaxError: assignment expression cannot rebind comprehension iteration variable 'j'
>>>
Python 3.8.0b4 (tags/v3.8.0b4:d93605d, Aug 29 2019, 23:21:28) [MSC v.1916 64 bit (AMD64)] on win32
>>> stuff = [(11, 22), (33, 44)]
>>> test = [i := 0 for i, j in stuff]
File "<stdin>", line 1
SyntaxError: assignment expression cannot rebind comprehension iteration variable 'i'
>>>
Python 3.8.0b4 (tags/v3.8.0b4:d93605d, Aug 29 2019, 23:21:28) [MSC v.1916 64 bit (AMD64)] on win32
>>> stuff = [11, 22, 33, 44]
>>> test = [i+1 for i in (i := stuff)]
File "<stdin>", line 1
SyntaxError: assignment expression cannot be used in a comprehension iterable expression
>>>
No change between version 3.8.0b4 and 3.8.0rc1.
No change between version 3.8.0rc1 and 3.8.0.
No TargetScopeError
or any other new exception class has been added in Python 3.8.