Open bslatkin opened 4 years ago
Here's the diff for the main part of the item to fix this:
-If a comprehension uses the walrus operator in the value part of the comprehension and doesn’t have a condition, it’ll leak the loop variable into the containing scope (see Item 21: “Know How Closures Interact with Variable Scope” for background):
+When a comprehension uses walrus operators, any corresponding variable names will be leaked into the containing scope (see Item 21: “Know How Closures Interact with Variable Scope” for background):
```python
-half = [(last := count // 2) for count in stock.values()]
-print(f'Last item of {half} is {last}')
+half = [(squared := last ** 2)
+ for count in stock.values()
+ if (last := count // 2) > 10]
+print(f'Last item of {half} is {last} ** 2 = {squared}')
-Last item of [62, 17, 4, 12] is 12
+Last item of [3844, 289, 144] is 12 ** 2 = 144
-This leakage of the loop variable is similar to what happens with a normal for
loop:
+The leakage of these variable names is similar to what happens with a normal for
loop:
-for count in stock.values(): # Leaks loop variable
- pass
-print(f'Last item of {list(stock.values())} is {count}')
+for count in stock.values():
+ last = count // 2
+ squared = last ** 2
+
+print(f'{count} // 2 = {last}; {last} ** 2 = {squared}')
-Last item of [125, 35, 8, 24] is 24
+24 // 2 = 12; 12 ** 2 = 144
-However, similar leakage doesn’t happen for the loop variables from comprehensions: +However, this leakage behavior can be surprising because when comprehensions don’t use assignment expressions the loop variable names won’t leak:
And this part needs to be removed entirely:
-It’s better not to leak loop variables, so I recommend using assignment expressions only in the condition part of a comprehension.
Thank you for reporting this errata. The original content felt odd from a language perspective and some experimentation in Python 3.8.1 showed a confusing result.
Reported by Mr. Kurokawa.
This sentence and the preceding example:
are no longer true. Python was changed between when this item was written and now. This is noted in the PEP:
https://www.python.org/dev/peps/pep-0572/#why-not-use-a-sublocal-scope-and-prevent-namespace-pollution
Example code that shows how the example in the book is no longer true (because
tenth
leaks):