New snippet: yielding from... return!

This commit is contained in:
Kislov Dmitry 2019-09-13 12:03:27 +10:00
parent 9f5dbbe4e9
commit cedbfba829
1 changed files with 59 additions and 0 deletions

59
README.md vendored
View File

@ -69,6 +69,7 @@ So, here we go...
- [ Be careful with chained operations](#-be-careful-with-chained-operations)
- [ Name resolution ignoring class scope](#-name-resolution-ignoring-class-scope)
- [ Needle in a Haystack](#-needle-in-a-haystack)
- [ Yielding from... return!](#-yielding-from-return)
- [Section: The Hidden treasures!](#section-the-hidden-treasures)
- [ Okay Python, Can you make me fly? *](#-okay-python-can-you-make-me-fly-)
- [ `goto`, but why? *](#-goto-but-why-)
@ -1883,6 +1884,64 @@ tuple()
---
### ▶ Yielding from... return!
1\.
```py
def func(k):
if k == 3:
return ["A string..."]
else:
yield from range(k)
```
**Output:**
```py
>>> list(func(3)) # expected: ["A string..."]
[]
```
The same behavior is true if we rewrite `yield from` as a for loop.
2\.
```py
def func(k):
if k == 3:
return ["A string..."]
else:
for j in range(k):
yield j
```
**Output:**
```py
>>> list(func(3)) # expected: ["A string..."]
[]
```
#### 💡 Explanation:
Starting from Python 3.3+ it became possible to use return statement
with values inside generators ([PEP380](https://www.python.org/dev/peps/pep-0380/)). The [official doc](https://www.python.org/dev/peps/pep-0380/#enhancements-to-stopiteration) says that "... `return expr` in a generator causes `StopIteration(expr)` to be raised upon exit from the generator."
So, to get `["A string..."]` from the generator `func` we need to catch `StopIteration`, e.g.:
```py
try:
next(func(3))
except StopIteration as e:
string = e.value
```
```py
>>> string
['A string...']
```
Note that `list(...)` automatically catches `StopIteration`. In case of `func(3)` `StopIteration` raises at the beginning because of `return` statement. Therefore, `list(func(3))` results in an empty list.
---
---