You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When an exception has been assigned using `as` target, it is cleared at the end of the except clause. This is as if
1306
+
When an exception has been assigned using `as` target, it is cleared at the end of the `except` clause. This is as if
1307
1307
1308
1308
```py
1309
1309
except E as N:
@@ -1378,8 +1378,75 @@ I've lost faith in truth!
1378
1378
1379
1379
---
1380
1380
1381
+
### ▶ Yielding from... return!
1382
+
1383
+
1\.
1384
+
1385
+
```py
1386
+
def some_func(x):
1387
+
if x == 3:
1388
+
return ["wtf"]
1389
+
else:
1390
+
yield from range(x)
1391
+
```
1392
+
1393
+
**Output:**
1394
+
1395
+
```py
1396
+
>>> list(some_func(3))
1397
+
[]
1398
+
```
1399
+
1400
+
Where did the `"wtf"` go? Is it due to some special effect of `yield from`? Let's validate that,
1401
+
1402
+
2\.
1403
+
1404
+
```py
1405
+
def some_func(x):
1406
+
if x == 3:
1407
+
return ["wtf"]
1408
+
else:
1409
+
for i in range(x):
1410
+
yield i
1411
+
```
1412
+
1413
+
**Output (> 3.3):**
1414
+
1415
+
```py
1416
+
>>> list(some_func(3))
1417
+
[]
1418
+
```
1419
+
1420
+
Same result, that didn't work either.
1421
+
1422
+
#### 💡 Explanation:
1423
+
1424
+
+ From Python 3.3 onwards, it became possible to use `return` statement with values inside generators (See [PEP380](https://www.python.org/dev/peps/pep-0380/)). The [official docs](https://www.python.org/dev/peps/pep-0380/#enhancements-to-stopiteration) say that,
1425
+
1426
+
> "... `return expr` in a generator causes `StopIteration(expr)` to be raised upon exit from the generator."
1427
+
1428
+
+ In case of `some_func(3)`, `StopIteration` is raised at the beginning because of `return` statement. The `StopIteration` exception is automatically catched inside the `list(...)` wrapper and the `for` loop. Therefore, the above two snippets result in an empty list.
1429
+
1430
+
+ To get `["wtf"]` from the generator `some_func` we need to catch the `StopIteration` exception,
1431
+
1432
+
```py
1433
+
try:
1434
+
next(some_func(3))
1435
+
except StopIteration as e:
1436
+
some_string = e.value
1437
+
```
1438
+
1439
+
```py
1440
+
>>> some_string
1441
+
["wtf"]
1442
+
```
1443
+
1444
+
---
1445
+
1381
1446
### ▶ Lossy zip of iterators
1447
+
1382
1448
<!-- Example ID: c28ed154-e59f-4070-8eb6-8967a4acac6d --->
1449
+
1383
1450
```py
1384
1451
>>> numbers = list(range(7))
1385
1452
>>> numbers
@@ -1407,8 +1474,7 @@ Where did element `3` go from the `numbers` list?
1407
1474
result = []
1408
1475
for it in iterators:
1409
1476
elem = next(it, sentinel)
1410
-
if elem is sentinel:
1411
-
return
1477
+
if elem is sentinel: return
1412
1478
result.append(elem)
1413
1479
yield tuple(result)
1414
1480
```
@@ -1605,7 +1671,9 @@ The built-in `ord()` function returns a character's Unicode [code point](https:/
1605
1671
---
1606
1672
1607
1673
### ▶ Teleportation
1674
+
1608
1675
<!-- Example ID: edafe923-0c20-4315-b6e1-0c31abfc38f5 --->
1676
+
1609
1677
```py
1610
1678
import numpy as np
1611
1679
@@ -1858,31 +1926,32 @@ print(x, ': x in global')
1858
1926
>>> x = 1
1859
1927
>>> print([x for x in range(5)])
1860
1928
[0, 1, 2, 3, 4]
1861
-
>>> print(x, ': x in global')
1862
-
(4, ': x in global')
1929
+
>>> print(x)
1930
+
4
1863
1931
```
1864
1932
1865
1933
**Output (Python 3.x):**
1866
1934
```
1867
1935
>>> x = 1
1868
1936
>>> print([x for x in range(5)])
1869
1937
[0, 1, 2, 3, 4]
1870
-
>>> print(x, ': x in global')
1871
-
1 : x in global
1938
+
>>> print(x)
1939
+
1
1872
1940
```
1873
1941
1874
1942
#### 💡 Explanation:
1875
1943
1876
1944
- In Python, for-loops use the scope they exist in and leave their defined loop-variable behind. This also applies if we explicitly defined the for-loop variable in the global namespace before. In this case, it will rebind the existing variable.
1877
1945
1878
-
- The differences in the output of Python 2.x and Python 3.x interpreters for list comprehension example can be explained by following change documented in [What’s New In Python 3.0](https://docs.python.org/3/whatsnew/3.0.html) documentation:
1946
+
- The differences in the output of Python 2.x and Python 3.x interpreters for list comprehension example can be explained by following change documented in [What’s New In Python 3.0](https://docs.python.org/3/whatsnew/3.0.html) change log:
1879
1947
1880
1948
> "List comprehensions no longer support the syntactic form `[... for var in item1, item2, ...]`. Use `[... for var in (item1, item2, ...)]` instead. Also, note that list comprehensions have different semantics: they are closer to syntactic sugar for a generator expression inside a `list()` constructor, and in particular the loop control variables are no longer leaked into the surrounding scope."
1881
1949
1882
1950
---
1883
1951
1884
1952
### ▶ Beware of default mutable arguments!
1885
1953
<!-- Example ID: 7d42dade-e20d-4a7b-9ed7-16fb58505fe9 --->
1954
+
1886
1955
```py
1887
1956
def some_func(default_arg=[]):
1888
1957
default_arg.append("some_string")
@@ -2182,39 +2251,6 @@ class SomeClass:
2182
2251
2183
2252
---
2184
2253
2185
-
### ▶ From full to None in one instruction
2186
-
2187
-
<!-- Example ID: 9a0d5335-efe5-4eae-af44-584d15233066 --->
2188
-
2189
-
```py
2190
-
some_list = [1, 2, 3]
2191
-
some_dict = {
2192
-
"key_1": 1,
2193
-
"key_2": 2,
2194
-
"key_3": 3
2195
-
}
2196
-
2197
-
some_list = some_list.append(4)
2198
-
some_dict = some_dict.update({"key_4": 4})
2199
-
```
2200
-
2201
-
**Output:**
2202
-
2203
-
```py
2204
-
>>> print(some_list)
2205
-
None
2206
-
>>> print(some_dict)
2207
-
None
2208
-
```
2209
-
2210
-
#### 💡 Explanation
2211
-
2212
-
2213
-
2214
-
---
2215
-
2216
-
2217
-
2218
2254
### ▶ Needles in a Haystack
2219
2255
2220
2256
<!-- Example ID: 52a199b1-989a-4b28-8910-dff562cebba9 --->
@@ -2235,6 +2271,7 @@ x, y = (0, 1) if True else None, None
2235
2271
```
2236
2272
2237
2273
2\.
2274
+
2238
2275
```py
2239
2276
t = ('one', 'two')
2240
2277
for i in t:
@@ -2249,6 +2286,7 @@ print(t)
2249
2286
```
2250
2287
2251
2288
**Output:**
2289
+
2252
2290
```py
2253
2291
one
2254
2292
two
@@ -2288,7 +2326,9 @@ ten_words_list = [
2288
2326
a = "python"
2289
2327
b = "javascript"
2290
2328
```
2329
+
2291
2330
**Output:**
2331
+
2292
2332
```py
2293
2333
# An assert statement with an assertion failure message.
2294
2334
>>> assert(a == b, "Both languages are different")
@@ -2329,97 +2369,35 @@ None
2329
2369
* `()` is a special token and denotes empty `tuple`.
2330
2370
2331
2371
* In 3, as you might have already figured out, there's a missing comma after 5th element (`"that"`) in the list. So by implicit string literal concatenation,
* No `AssertionError` was raised in 4th snippet because instead of asserting the individual expression `a == b`, we're asserting entire tuple. The following snippet will clear things up,
2338
-
```py
2339
-
>>> a = "python"
2340
-
>>> b = "javascript"
2341
-
>>> assert a == b
2342
-
Traceback (most recent call last):
2343
-
File "<stdin>", line 1, in <module>
2344
-
AssertionError
2345
-
2346
-
>>> assert (a == b, "Values are not equal")
2347
-
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
2348
-
2349
-
>>> assert a == b, "Values are not equal"
2350
-
Traceback (most recent call last):
2351
-
File "<stdin>", line 1, in <module>
2352
-
AssertionError: Values aren not equal
2353
-
```
2354
-
2355
-
* As for the last snippet, most methods that modify the items of sequence/mapping objects like `list.append`, `dict.update`, `list.sort`, etc. modify the objects in-place and return `None`. The rationale behind this is to improve performance by avoiding making a copy of the object if the operation can be done in-place (Referred from [here](http://docs.python.org/2/faq/design.html#why-doesn-t-list-sort-return-the-sorted-list)).
2356
-
2357
-
* Being aware of these knitpicks can save you hours of degugging effort in long run.
2358
-
2359
-
---
2360
-
2361
-
### ▶ Yielding from... return!
2362
-
2363
-
1\.
2364
-
2365
-
```py
2366
-
def some_func(x):
2367
-
if x == 3:
2368
-
return ["wtf"]
2369
-
else:
2370
-
yield from range(x)
2371
-
```
2372
-
2373
-
**Output:**
2374
-
2375
-
```py
2376
-
>>> list(some_func(3))
2377
-
[]
2378
-
```
2379
2372
2380
-
Where did the `"wtf"` go? Is it due to some special effect of `yield from`? Let's validate that,
2381
-
2382
-
2\.
2383
-
2384
-
```py
2385
-
def some_func(x):
2386
-
if x == 3:
2387
-
return ["wtf"]
2388
-
else:
2389
-
for i in range(x):
2390
-
yield i
2391
-
```
2392
-
2393
-
**Output (> 3.3):**
2394
-
2395
-
```py
2396
-
>>> list(some_func(3))
2397
-
[]
2398
-
```
2399
-
2400
-
Same result, that didn't work either.
2401
-
2402
-
#### 💡 Explanation:
2403
-
2404
-
+ From Python 3.3 onwards, it became possible to use `return` statement with values inside generators (See [PEP380](https://www.python.org/dev/peps/pep-0380/)). The [official docs](https://www.python.org/dev/peps/pep-0380/#enhancements-to-stopiteration) say that,
2405
-
2406
-
> "... `return expr` in a generator causes `StopIteration(expr)` to be raised upon exit from the generator."
2407
-
2408
-
+ In case of `some_func(3)`, `StopIteration` is raised at the beginning because of `return` statement. The `StopIteration` exception is automatically catched inside the `list(...)` wrapper and the `for` loop. Therefore, the above two snippets result in an empty list.
2409
-
2410
-
+ To get `["wtf"]` from the generator `some_func` we need to catch the `StopIteration` exception,
* No `AssertionError` was raised in 4th snippet because instead of asserting the individual expression `a == b`, we're asserting entire tuple. The following snippet will clear things up,
2379
+
2418
2380
```py
2419
-
>>> some_string
2420
-
["wtf"]
2381
+
>>> a = "python"
2382
+
>>> b = "javascript"
2383
+
>>> assert a == b
2384
+
Traceback (most recent call last):
2385
+
File "<stdin>", line 1, in <module>
2386
+
AssertionError
2387
+
2388
+
>>> assert (a == b, "Values are not equal")
2389
+
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
2390
+
2391
+
>>> assert a == b, "Values are not equal"
2392
+
Traceback (most recent call last):
2393
+
File "<stdin>", line 1, in <module>
2394
+
AssertionError: Values aren not equal
2421
2395
```
2422
2396
2397
+
* As for the last snippet, most methods that modify the items of sequence/mapping objects like `list.append`, `dict.update`, `list.sort`, etc. modify the objects in-place and return `None`. The rationale behind this is to improve performance by avoiding making a copy of the object if the operation can be done in-place (Referred from [here](http://docs.python.org/2/faq/design.html#why-doesn-t-list-sort-return-the-sorted-list)).
2398
+
2399
+
* Being aware of these knitpicks can save you hours of degugging effort in long run.
0 commit comments