Skip to content

Commit cedbfba

Browse files
committed
New snippet: yielding from... return!
1 parent 9f5dbbe commit cedbfba

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ So, here we go...
6969
- [▶ Be careful with chained operations](#-be-careful-with-chained-operations)
7070
- [▶ Name resolution ignoring class scope](#-name-resolution-ignoring-class-scope)
7171
- [▶ Needle in a Haystack](#-needle-in-a-haystack)
72+
- [▶ Yielding from... return!](#-yielding-from-return)
7273
- [Section: The Hidden treasures!](#section-the-hidden-treasures)
7374
- [▶ Okay Python, Can you make me fly? *](#-okay-python-can-you-make-me-fly-)
7475
- [`goto`, but why? *](#-goto-but-why-)
@@ -1883,6 +1884,64 @@ tuple()
18831884
18841885
---
18851886
1887+
### ▶ Yielding from... return!
1888+
1889+
1\.
1890+
```py
1891+
def func(k):
1892+
if k == 3:
1893+
return ["A string..."]
1894+
else:
1895+
yield from range(k)
1896+
```
1897+
1898+
**Output:**
1899+
```py
1900+
>>> list(func(3)) # expected: ["A string..."]
1901+
[]
1902+
```
1903+
1904+
The same behavior is true if we rewrite `yield from` as a for loop.
1905+
1906+
2\.
1907+
```py
1908+
def func(k):
1909+
if k == 3:
1910+
return ["A string..."]
1911+
else:
1912+
for j in range(k):
1913+
yield j
1914+
```
1915+
1916+
**Output:**
1917+
```py
1918+
>>> list(func(3)) # expected: ["A string..."]
1919+
[]
1920+
```
1921+
1922+
#### 💡 Explanation:
1923+
1924+
Starting from Python 3.3+ it became possible to use return statement
1925+
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."
1926+
1927+
So, to get `["A string..."]` from the generator `func` we need to catch `StopIteration`, e.g.:
1928+
1929+
```py
1930+
try:
1931+
next(func(3))
1932+
except StopIteration as e:
1933+
string = e.value
1934+
```
1935+
1936+
```py
1937+
>>> string
1938+
['A string...']
1939+
```
1940+
1941+
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.
1942+
1943+
---
1944+
18861945
---
18871946
18881947

0 commit comments

Comments
 (0)