diff --git a/pythonetc/3.9/decorators.md b/pythonetc/3.9/decorators.md
index 41defd8..127e646 100644
--- a/pythonetc/3.9/decorators.md
+++ b/pythonetc/3.9/decorators.md
@@ -1,3 +1,7 @@
+# decorators (PEP-614)
+
+Published: 18 June 2020, 18:00
+
[Syntax for decorators is limited](https://t.me/pythonetc/16) by getting attributes and calling objects:
```python
diff --git a/pythonetc/3.9/generic-types.md b/pythonetc/3.9/generic-types.md
index b7d28fc..80ad237 100644
--- a/pythonetc/3.9/generic-types.md
+++ b/pythonetc/3.9/generic-types.md
@@ -1,3 +1,7 @@
+# generic built-in types (PEP-585)
+
+Published: 09 June 2020, 18:00
+
More cool things from Python 3.9. [PEP-585](https://www.python.org/dev/peps/pep-0585/) introduced generic types support for the built-in types:
```python
diff --git a/pythonetc/3.9/merge-dicts.md b/pythonetc/3.9/merge-dicts.md
index 773b3da..ad3663f 100644
--- a/pythonetc/3.9/merge-dicts.md
+++ b/pythonetc/3.9/merge-dicts.md
@@ -1,25 +1,29 @@
+# `dict.__or__` (PEP-584)
+
+Published: 04 June 2020, 18:00
+
There are a lot of ways to merge two dicts:
1. Long but simple:
-```python
-merged = d1.copy()
-merged.update(d2)
-```
+ ```python
+ merged = d1.copy()
+ merged.update(d2)
+ ```
-2. [Unpacking](https://t.me/pythonetc/538):
+1. [Unpacking](https://t.me/pythonetc/538):
-```python
-merged = {**d1, **d2}
-```
+ ```python
+ merged = {**d1, **d2}
+ ```
-3. Unpacking again (keys must be strings):
+1. Unpacking again (keys must be strings):
-```python
-merged = dict(d1, **d2)
-```
+ ```python
+ merged = dict(d1, **d2)
+ ```
-4. `collections.ChainMap`. Result is not `dict` but so.
+1. `collections.ChainMap`. Result is not `dict` but so.
In python 3.9, [PEP-584](https://www.python.org/dev/peps/pep-0584/) introduced the 5th way. Meet the `|` operator for `dict`!
diff --git a/pythonetc/3.9/str-removeprefix.md b/pythonetc/3.9/str-removeprefix.md
index 6ff86c9..8d1b606 100644
--- a/pythonetc/3.9/str-removeprefix.md
+++ b/pythonetc/3.9/str-removeprefix.md
@@ -1,3 +1,7 @@
+# str.removeprefix
+
+Published: 28 May 2020, 18:00
+
In python 3.9, [PEP-616](https://www.python.org/dev/peps/pep-0616/) introduced `str.removeprefix` and `str.removesuffix` methods:
```python
diff --git a/pythonetc/3.9/unparse.md b/pythonetc/3.9/unparse.md
index 3cf4d0e..76c8a46 100644
--- a/pythonetc/3.9/unparse.md
+++ b/pythonetc/3.9/unparse.md
@@ -1,3 +1,7 @@
+# ast.unparse
+
+Published: 16 June 2020, 18:00
+
Python 3.9 introduces a new function [ast.unparse](https://docs.python.org/3.9/library/ast.html#ast.unparse). It accepts a parsed AST and produces a Python code. This code if parsed will produce the same AST:
```python
diff --git a/pythonetc/README.md b/pythonetc/README.md
index e575572..81349c5 100644
--- a/pythonetc/README.md
+++ b/pythonetc/README.md
@@ -1,97 +1,19 @@
# Python etc
-## Schedule
+These are the posts I made for [@pythonetc](https://t.me/s/pythonetc).
-1. ./intro.md (26 May 2020, 18:00)
+Reasons to read posts from the cannel rather than here:
-A bit of history and 3.9:
+1. The publication order matters because some posts reference previous posts.
+1. Some of the drafts here aren't published yet, so here are some spoilers.
+1. Sometimes, we publish corrections to some already published posts. Not all corrections get here.
+1. It's good to have stat on views count and likes in one place.
+1. This is only the second season, made by me. The previous season was made by @pushtaev and it also has tons of great information.
-1. ./3.9/str-removeprefix.md (28 May 2020, 18:00)
-1. ./hist/backquotes.md (02 June 2020, 18:00)
-1. ./3.9/merge-dicts.md (04 June 2020, 18:00)
-1. ./3.9/generic-types.md (09 June 2020, 18:00)
-1. ./hist/types.md (11 June 2020, 18:00)
-1. ./3.9/unparse.md (16 June 2020, 18:00)
-1. ./3.9/decorators.md (18 June 2020, 18:00)
+You don't need telegram to read the channel using the link above. If neither of it stops you, sure, go ahead, read it here.
-Frames:
+## To schedule
-1. ./recursion.md (23 June 2020, 18:00)
-1. ./snippets/f-strings.md (25 June 2020, 18:00)
-1. ./snippets/sum-frames.md (30 June 2020, 18:00)
-
-Classes, metaclasses, and descriptors:
-
-1. ./class-body.md (02 July 2020, 18:00)
-1. ./init-subclass.md (07 July 2020, 18:00)
-1. ./prepare.md (09 July 2020, 18:00)
-1. ./data-descriptors.md (14 July 2020, 18:00)
-1. ./cached-property.md (16 July 2020, 18:00)
-1. ./set-name.md (21 July 2020, 18:00)
-
-More:
-
-1. ./dunder.md (23 July 2020, 18:00)
-1. ./magic.md (28 July 2020, 18:00)
-1. ./assert.md (30 July 2020, 18:00)
-1. ./colorsys.md (04 August 2020, 18:00)
-1. ./snippets/final.md (06 August 2020, 18:00)
-1. ./snippets/getitem.md (11 August 2020, 18:00)
-1. ./license.md (13 August 2020, 18:00)
-1. ./fnmatch.md (18 August 2020, 18:00)
-1. ./snippets/hamming.md (20 August 2020, 18:00)
-1. ./literal-eval.md (25 August 2020, 18:00)
-1. ./zen.md (27 August 2020, 18:00)
-1. ./nan.md (01 September 2020, 18:00)
-1. ./snippets/itertools.md (03 September 2020, 18:00)
-1. ./format.md (08 September 2020, 18:00)
-1. ./object-type.md (10 September 2020, 18:00)
-1. ./objects.md (15 September 2020, 18:00)
-1. ./sys-modules.md (17 September 2020, 18:00)
-1. ./numbers.md (22 September 2020, 18:00)
-1. ./simplenamespace.md (24 September 2020, 18:00)
-1. ./snippets/to-str.md (29 September 2020, 18:00)
-1. ./nullcontext.md (01 October 2020, 18:00)
-1. ./enum.md (06 October 2020, 18:00)
-1. ./dynamic-class-attribute.md (08 October 2020, 18:00)
-1. ./zipapp.md (13 October 2020, 18:00)
-1. ./new-init.md (15 October 2020, 18:00)
-1. ./sentinel.md (20 October 2020, 18:00)
-1. ./yield-compr.md (22 October 2020, 18:00)
-1. ./f-docstrings.md (27 October 2020, 18:00)
-1. ./codecs.md (29 October 2020, 18:00)
-1. ./comprehension-func.md (03 November 2020, 18:00)
-1. ./slots-docs.md (05 November 2020, 18:00)
-1. ./pydoc.md (10 November 2020, 18:00)
-1. ./class-getitem.md (12 November 2020, 18:00)
-1. ./ipaddress.md (17 November 2020, 18:00)
-1. ./index.md (19 November 2020, 18:00)
-1. ./qualname.md (24 November 2020, 18:00)
-1. ./digits.md (26 November 2020, 18:00)
-1. ./emoji.md (01 December 2020, 18:00)
-1. ./json-default.md (03 December 2020, 18:00)
-1. ./ipython.md (08 December 2020, 18:00)
-1. ./array.md (10 December 2020, 18:00)
-1. ./lru-cache.md (15 December 2020, 18:00)
-1. ./functools-cache.md (17 December 2020, 18:00)
-1. ./re-compile.md (22 December 2020, 18:00)
-1. ./tau.md (24 December 2020, 18:00)
-1. ./str-append.md (29 December 2020, 18:00)
-1. ./new-year.md (31 December 2020, 18:00)
-1. ./scopes.md (25 February 2021, 18:00)
-1. ./nonlocal.md (02 March 2021, 18:00)
-1. ./str-concat.md (04 March 2021, 18:00)
-1. ./bytearray.md (09 March 2021, 18:00)
-1. ./join-lists.md (11 March 2021, 18:00)
-1. ./is-warning.md (16 March 2021, 18:00)
-1. ./float.md (18 March 2021, 18:00)
-1. ./inf.md (23 March 2021, 18:00)
-1. ./typed-dict.md (25 March 2021, 18:00)
-1. ./getattr-annotation.md (30 March 2021, 18:00)
-1. ./eval-strategy.md (01 April 2021, 18:00)
-1. ./deepcopy.md (6 April 2021, 18:00)
-1. ./eval-order.md (8 April 2021, 18:00)
-1. ./key-error.md (15 April 2021, 18:00)
1. ./exc-info.md
1. ./log-extra.md
1. ./dedent.md
@@ -101,39 +23,34 @@ More:
1. ./json-allow-nan.md
1. ./sre-parse.md
-Out of order:
-
-1. ./match.md (26 June 2020, 18:00)
-1. ./snippets/to-str-2.md (30 September 2020, 18:00)
-1. ./class-scope.md (27 January 2021, 19:00)
-1. ./season25.md (24 February 2021, 16:20)
-
-## TODO
-
-Json indent
-Csv instead of xls
-Turtle
-Subprocess and env vars
-Subprocess pipe
-Unicode module
-String.Template
-String module consts
-Urllib
-https://bugs.python.org/issue36326
-str[0][0][0]
-https://www.python.org/downloads/release/python-3100a4/
-https://www.python.org/dev/peps/pep-0505/
-`__dir__`
-ModuleType
-Import hooks
-TypeVar
-Bare except
-Lookup error
-Make your own exceptions
-When to use is
-In uses hash, not eq
-super()
-gc
-trace
-atexit
-Lazy annotations hype
+## To write
+
+These are ideas for future posts. Let me know if you want to write a guest post on any of these topics.
+
++ Json indent
++ Csv instead of xls
++ Turtle
++ Subprocess and env vars
++ Subprocess pipe
++ Unicode module
++ String.Template
++ String module consts
++ Urllib
++ https://bugs.python.org/issue36326
++ str[0][0][0]
++ https://www.python.org/downloads/release/python-3100a4/
++ https://www.python.org/dev/peps/pep-0505/
++ `__dir__`
++ ModuleType
++ Import hooks
++ TypeVar
++ Bare except
++ Lookup error
++ Make your own exceptions
++ When to use is
++ In uses hash, not eq
++ super()
++ gc
++ trace
++ atexit
++ Lazy annotations hype
diff --git a/pythonetc/array.md b/pythonetc/array.md
index b178216..ac1ba71 100644
--- a/pythonetc/array.md
+++ b/pythonetc/array.md
@@ -1,3 +1,7 @@
+# array performance
+
+Published: 10 December 2020, 18:00
+
The module [array](https://t.me/pythonetc/124) is helpful if you want to be memory efficient or interoperate with C. However, working with array can be slower than with list:
```python
diff --git a/pythonetc/assert.md b/pythonetc/assert.md
index e24fdce..41eab68 100644
--- a/pythonetc/assert.md
+++ b/pythonetc/assert.md
@@ -1,3 +1,7 @@
+# assert
+
+Published: 30 July 2020, 18:00
+
Basically, `assert` could be a function:
```python
diff --git a/pythonetc/bytearray.md b/pythonetc/bytearray.md
index 249e05e..84a1b1e 100644
--- a/pythonetc/bytearray.md
+++ b/pythonetc/bytearray.md
@@ -1,3 +1,7 @@
+# bytearray
+
+Published: 09 March 2021, 18:00
+
Types `str` and `bytes` are immutable. As we learned in previous posts, `+` is optimized for `str` but sometimes you need a fairly mutable type. For such cases, there is `bytearray` type. It is a "hybrid" of `bytes` and `list`:
```python
diff --git a/pythonetc/cached-property.md b/pythonetc/cached-property.md
index c7b5fdb..b63b8c5 100644
--- a/pythonetc/cached-property.md
+++ b/pythonetc/cached-property.md
@@ -1,3 +1,7 @@
+# @cached_property
+
+Published: 16 July 2020, 18:00
+
Decorator `@cached_property` is an amazing way to simplify your code. It's like the regular `@property` but remembers the value after the first call:
```python
diff --git a/pythonetc/class-body.md b/pythonetc/class-body.md
index 28e4c29..5e28876 100644
--- a/pythonetc/class-body.md
+++ b/pythonetc/class-body.md
@@ -1,3 +1,7 @@
+# class body
+
+Published: 02 July 2020, 18:00
+
The class body is the same as, let's say, the function body, [with only a few limitations](https://t.me/pythonetc/438). You can put any statements inside, reuse previous results and so on:
```python
diff --git a/pythonetc/class-getitem.md b/pythonetc/class-getitem.md
index 3465b0a..640792c 100644
--- a/pythonetc/class-getitem.md
+++ b/pythonetc/class-getitem.md
@@ -1,3 +1,7 @@
+# `__class_getitem__` (PEP-560)
+
+Published: 12 November 2020, 18:00
+
[PEP-560](https://www.python.org/dev/peps/pep-0560/) (landed in Python 3.7) introduced a new magic method `__class_getitem__`. it is the same as `__getitem__` but for not instancinated class. The main motivation is easier type annotation support for generic collections like `List[int]` or `Type[Dict[str, int]]`:
```python
diff --git a/pythonetc/class-scope.md b/pythonetc/class-scope.md
index 6e6d458..182d54e 100644
--- a/pythonetc/class-scope.md
+++ b/pythonetc/class-scope.md
@@ -1,3 +1,7 @@
+# class scope
+
+Published: 27 January 2021, 19:00
+
Today Guido van Rossum [posted a Python riddle](https://twitter.com/gvanrossum/status/1354305179244392453):
```python
diff --git a/pythonetc/codecs.md b/pythonetc/codecs.md
index 155059d..20099ba 100644
--- a/pythonetc/codecs.md
+++ b/pythonetc/codecs.md
@@ -1,3 +1,7 @@
+# codecs
+
+Published: 29 October 2020, 18:00
+
The module [codecs](https://docs.python.org/3/library/codecs.html) provides `encode` and `decode` function to encode and decode (wow!) text in different encodings, like UTF8, CP1251, [Punycode](https://en.wikipedia.org/wiki/Punycode), [IDNA](https://en.wikipedia.org/wiki/Internationalized_domain_name), [ROT13](https://en.wikipedia.org/wiki/ROT13), execute [escape sequences](https://en.wikipedia.org/wiki/Escape_sequence), etc.
```python
diff --git a/pythonetc/colorsys.md b/pythonetc/colorsys.md
index 2c2a669..fc3968c 100644
--- a/pythonetc/colorsys.md
+++ b/pythonetc/colorsys.md
@@ -1,3 +1,7 @@
+# colorsys
+
+Published: 04 August 2020, 18:00
+
The [colorsys](https://docs.python.org/3/library/colorsys.html) module converts colors between different [representations](https://en.wikipedia.org/wiki/Color_model): RGB, YIQ, HLS, and HSV. Yes, it is in the stdlib!
```python
diff --git a/pythonetc/comprehension-func.md b/pythonetc/comprehension-func.md
index 9a40926..68137c5 100644
--- a/pythonetc/comprehension-func.md
+++ b/pythonetc/comprehension-func.md
@@ -1,3 +1,7 @@
+# comprehensions are functions
+
+Published: 03 November 2020, 18:00
+
As we said, comprehensions compiled into functions. That means, we can take a [types.CodeType](https://docs.python.org/3.8/library/types.html#types.CodeType) object for a comprehension, wrap it into [types.FunctionType](https://docs.python.org/3.8/library/types.html#types.FunctionType), and get a function.
```python
diff --git a/pythonetc/data-descriptors.md b/pythonetc/data-descriptors.md
index 9e61bbb..82ef2fd 100644
--- a/pythonetc/data-descriptors.md
+++ b/pythonetc/data-descriptors.md
@@ -1,3 +1,7 @@
+# data and non-data descriptors
+
+Published: 14 July 2020, 18:00
+
[Descriptors](https://docs.python.org/3/howto/descriptor.html) are special class attributes with a custom behavior on attribute get, set, or delete. If an object defines `__set__` or `__delete__`, it is considered a data descriptor. Descriptors that only define `__get__` are called non-data descriptors. The difference is that non-data descriptors are called only if the attribute isn't presented in `__dict__` of the instance.
Non-data descriptor:
diff --git a/pythonetc/deepcopy.md b/pythonetc/deepcopy.md
index 6ecd6ac..2ce071d 100644
--- a/pythonetc/deepcopy.md
+++ b/pythonetc/deepcopy.md
@@ -1,3 +1,7 @@
+# copy.deepcopy
+
+Published: 6 April 2021, 18:00
+
What if we want to modify a collection inside a function but don't want these modifications to affect the caller code? Then we should explicitly copy the value.
For this purpose, all mutable built-in collections provide method `.copy`:
diff --git a/pythonetc/digits.md b/pythonetc/digits.md
index b633a08..9e26fae 100644
--- a/pythonetc/digits.md
+++ b/pythonetc/digits.md
@@ -1,3 +1,7 @@
+# str.isdigit
+
+Published: 26 November 2020, 18:00
+
We use Arabic digits to record numbers. However, there are many more numeral systems: Chinese (and Suzhou), Chakma, Persian, Hebrew, and so on. And Python supports them when detecting numbers:
```python
diff --git a/pythonetc/dunder.md b/pythonetc/dunder.md
index b17153f..9f53705 100644
--- a/pythonetc/dunder.md
+++ b/pythonetc/dunder.md
@@ -1 +1,5 @@
+# dunder
+
+Published: 23 July 2020, 18:00
+
How do you read `__init__` word? "underscore underscore init underscore underscore"? Just "init"? There is a convention to read it "dunder init". it was [proposed by Mark Jackson](https://lists.gt.net/python/python/124634#124634) in 2002 and [popularized by Ned Batchelder](https://nedbatchelder.com/blog/200605/dunder.html) in 2006.
diff --git a/pythonetc/dynamic-class-attribute.md b/pythonetc/dynamic-class-attribute.md
index a50e818..0d58b17 100644
--- a/pythonetc/dynamic-class-attribute.md
+++ b/pythonetc/dynamic-class-attribute.md
@@ -1,3 +1,7 @@
+# types.DynamicClassAttribute
+
+Published: 08 October 2020, 18:00
+
[types.DynamicClassAttribute](https://docs.python.org/3/library/types.html#types.DynamicClassAttribute) is a decorator that allows having a `@property` that behaves differently when it's called from the class and when from the instance.
```python
diff --git a/pythonetc/emoji.md b/pythonetc/emoji.md
index 0cdc26b..e555907 100644
--- a/pythonetc/emoji.md
+++ b/pythonetc/emoji.md
@@ -1,3 +1,7 @@
+# emojis
+
+Published: 01 December 2020, 18:00
+
Python has rich support for Unicode, including referencing glyphs (including emojis, of course) by name.
Get glyph name:
@@ -18,7 +22,7 @@ Convert name to a glyph:
# '🤣'
```
-A good thing is that f-string also don't confused by named unicode glyphs:
+A good thing is that f-strings also aren't confused by named unicode glyphs:
```python
fire = 'hello'
diff --git a/pythonetc/enum.md b/pythonetc/enum.md
index d82c383..dd7a736 100644
--- a/pythonetc/enum.md
+++ b/pythonetc/enum.md
@@ -1,3 +1,7 @@
+# enum
+
+Published: 06 October 2020, 18:00
+
The module [enum](https://docs.python.org/3/library/enum.html) provides a way to build an enumerable class. It is a class with a predefined list of instances, and every instance is bound to a unique constant value.
```python
diff --git a/pythonetc/eval-order.md b/pythonetc/eval-order.md
index ded14fe..c14d08c 100644
--- a/pythonetc/eval-order.md
+++ b/pythonetc/eval-order.md
@@ -1,3 +1,7 @@
+# eval order
+
+Published: 8 April 2021, 18:00
+
Python uses [eager evaluation](https://en.wikipedia.org/wiki/Eager_evaluation). When a function is called, all its arguments are evaluated from left to right and only then their results are passed into the function:
```python
diff --git a/pythonetc/eval-strategy.md b/pythonetc/eval-strategy.md
index cedd0d3..6a6b55a 100644
--- a/pythonetc/eval-strategy.md
+++ b/pythonetc/eval-strategy.md
@@ -1,3 +1,7 @@
+# eval strategy
+
+Published: 01 April 2021, 18:00
+
In most of the programming languages (like C, PHP, Go, Rust) values can be passed into a function either as value or as reference (pointer):
+ [Call by value](https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value) means that the value of the variable is copied, so all modification with the argument value inside the function won't affect the original value. This is an example of how it works in [Go](https://golang.org/):
diff --git a/pythonetc/exc-info.md b/pythonetc/exc-info.md
index 7025696..7c66a29 100644
--- a/pythonetc/exc-info.md
+++ b/pythonetc/exc-info.md
@@ -25,7 +25,7 @@ update_channel('telegram', 'Telegram News')
This example has a few issues:
+ There is no explicit log message. So, when it fails, you can't search in the project where this log record comes from.
-+ There is no traceback. When the `try` block execution is more complicated, we want to be able to track where exactly an the call stack the exception occured. To achieve it, logger methods provide `exc_info` argument. When it is set to `True`, the current exception with traceback will be added into the log message.
++ There is no traceback. When the `try` block execution is more complicated, we want to be able to track where exactly in the call stack the exception occurred. To achieve it, logger methods provide `exc_info` argument. When it is set to `True`, the current exception with traceback will be added to the log message.
So, this is how we can do it better:
@@ -45,7 +45,7 @@ update_channel('telegram', 'Telegram News')
# KeyError: 'telegram'
```
-Also, logger provides a convenient method `exception` which is the same as `error` with `exc_info=True`:
+Also, the logger provides a convenient method `exception` which is the same as `error` with `exc_info=True`:
```python
logger.exception('channel not found')
diff --git a/pythonetc/f-docstrings.md b/pythonetc/f-docstrings.md
index e954aae..52a9fff 100644
--- a/pythonetc/f-docstrings.md
+++ b/pythonetc/f-docstrings.md
@@ -1,3 +1,7 @@
+# f-strings and docstrings
+
+Published: 27 October 2020, 18:00
+
Docstring is a string that goes before all other statements in the function body (comments are ignored):
```python
diff --git a/pythonetc/float.md b/pythonetc/float.md
index 543e015..de06a51 100644
--- a/pythonetc/float.md
+++ b/pythonetc/float.md
@@ -1,3 +1,7 @@
+# float (IEEE 754)
+
+Published: 18 March 2021, 18:00
+
[Floating point numbers](https://en.wikipedia.org/wiki/Floating-point_arithmetic) in Python and most of the modern languages are implemented according to [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754). The most interesting and hardcore part is "arithmetic formats" which defines a few special values:
+ `inf` and `-inf` representing infinity.
diff --git a/pythonetc/fnmatch.md b/pythonetc/fnmatch.md
index 5addc6a..b6e8bd0 100644
--- a/pythonetc/fnmatch.md
+++ b/pythonetc/fnmatch.md
@@ -1,3 +1,7 @@
+# fnmatch
+
+Published: 18 August 2020, 18:00
+
Module [fnmatch](https://docs.python.org/3/library/fnmatch.html) provides a few functions to work with Unix-like patterns:
```python
diff --git a/pythonetc/format.md b/pythonetc/format.md
index 32adaea..fbd46a7 100644
--- a/pythonetc/format.md
+++ b/pythonetc/format.md
@@ -1,3 +1,7 @@
+# format
+
+Published: 08 September 2020, 18:00
+
There is a built-in function `format` that basically just calls `__format__` method of the passed argument type with passed spec. It is used in `str.format` as well.
```python
diff --git a/pythonetc/functools-cache.md b/pythonetc/functools-cache.md
index af6202f..3c42610 100644
--- a/pythonetc/functools-cache.md
+++ b/pythonetc/functools-cache.md
@@ -1,3 +1,7 @@
+# functools.cache
+
+Published: 17 December 2020, 18:00
+
The decorator `functools.lru_cache` named so because of the underlying cache replacement policy. When the cache size limit is reached [Least Recently Used](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_.28LRU.29) records removed first:
```python
diff --git a/pythonetc/getattr-annotation.md b/pythonetc/getattr-annotation.md
index 36fa97b..07e7303 100644
--- a/pythonetc/getattr-annotation.md
+++ b/pythonetc/getattr-annotation.md
@@ -1,3 +1,7 @@
+# getattr type annotaions (PEP-526)
+
+Published: 30 March 2021, 18:00
+
[PEP-526](https://www.python.org/dev/peps/pep-0526/), introducing syntax for variable annotations (laded in Python 3.6), allows annotating any valid assignment target:
```python
diff --git a/pythonetc/hist/backquotes.md b/pythonetc/hist/backquotes.md
index a828ffd..ccfc341 100644
--- a/pythonetc/hist/backquotes.md
+++ b/pythonetc/hist/backquotes.md
@@ -1,3 +1,7 @@
+# backquotes
+
+Published: 02 June 2020, 18:00
+
Python from the very first release and until Python 2.7 supported backquotes as a shortcut for `repr(...)`:
```python
diff --git a/pythonetc/hist/types.md b/pythonetc/hist/types.md
index 24c57c1..f8edbbf 100644
--- a/pythonetc/hist/types.md
+++ b/pythonetc/hist/types.md
@@ -1,3 +1,7 @@
+# types
+
+Published: 11 June 2020, 18:00
+
An interesting story is behind [types](https://docs.python.org/3/library/types.html) module. Until Python 2.7, it had types like `IntType`, `TupleType`, `UnicodeType`, and so on. The motivation behind is that before Python 2.4 built-in functions like `int` and `str` were constructors for the types but not the types itself. Hence they couldn't be used in type checks:
```python
diff --git a/pythonetc/index.md b/pythonetc/index.md
index 5182d1a..6227e57 100644
--- a/pythonetc/index.md
+++ b/pythonetc/index.md
@@ -1,3 +1,7 @@
+# `__index__` (PEP-357)
+
+Published: 19 November 2020, 18:00
+
In Python 2.5, [PEP-357](https://www.python.org/dev/peps/pep-0357/) allowed any object to be passed as index or slice into `__getitem__`:
```python
diff --git a/pythonetc/inf.md b/pythonetc/inf.md
index 0a898c2..21247da 100644
--- a/pythonetc/inf.md
+++ b/pythonetc/inf.md
@@ -1,3 +1,7 @@
+# float division
+
+Published: 23 March 2021, 18:00
+
Infinity has an interesting behavior on division operations. Some of them are expected, some of them are surprising. Without further talking, there is a table:
```python
diff --git a/pythonetc/init-subclass.md b/pythonetc/init-subclass.md
index 564a198..46671b8 100644
--- a/pythonetc/init-subclass.md
+++ b/pythonetc/init-subclass.md
@@ -1,3 +1,7 @@
+# `__init_subclass__` (PEP-487)
+
+Published: 07 July 2020, 18:00
+
Python 3.6 introduced a few hooks to simplify things that could be done before only with metaclasses. Thanks to [PEP-487](https://www.python.org/dev/peps/pep-0487/). The most useful such hook is `__init_subclass__`. It is called on subclass creation and accepts the class and keyword arguments passed next to base classes. Let's see an example:
```python
diff --git a/pythonetc/intro.md b/pythonetc/intro.md
index 59f1eac..f3e1bcd 100644
--- a/pythonetc/intro.md
+++ b/pythonetc/intro.md
@@ -1,14 +1,18 @@
+# intro (season 2)
+
+Published: 26 May 2020, 18:00
+
Welcome to season 2! In the next episodes:
1. New cool features in Python 3.9 (the final release is planned on 2020-10-05).
-2. Python history and features that were removed.
-3. PEPs in the "draft" status that aren't accepted nor rejected yet.
-4. Short and useful code snippets to empower your code.
-5. A lot more features and tricks, like in good old season 1.
+1. Python history and features that were removed.
+1. PEPs in the "draft" status that aren't accepted nor rejected yet.
+1. Short and useful code snippets to empower your code.
+1. A lot more features and tricks, like in good old season 1.
Also, a few updates:
1. @orsinium joins the @pythonetc team.
-2. No ad in this season. [Support us on ko-fi](https://ko-fi.com/pythonetc) if you like it!
+1. No ad in this season. [Support us on ko-fi](https://ko-fi.com/pythonetc) if you like it!
The show must go on!
diff --git a/pythonetc/ipaddress.md b/pythonetc/ipaddress.md
index 7cafa79..b8a2c92 100644
--- a/pythonetc/ipaddress.md
+++ b/pythonetc/ipaddress.md
@@ -1,3 +1,7 @@
+# ipaddress
+
+Published: 17 November 2020, 18:00
+
[ipaddress](https://docs.python.org/3/library/ipaddress.html) provides capabilities to work with IP addresses and networks (both IPv4 and IPv6).
```python
diff --git a/pythonetc/ipython.md b/pythonetc/ipython.md
index 489e23f..5c71cc6 100644
--- a/pythonetc/ipython.md
+++ b/pythonetc/ipython.md
@@ -1,3 +1,7 @@
+# ipython
+
+Published: 08 December 2020, 18:00
+
[IPython](https://ipython.org/) is an alternative interactive shell for Python. It has syntax highlighting, powerful introspection and autocomplete, searchable cross-session history, and much more. Run `%quickref` in IPython to get a quick reference on useful commands and shortcuts. Some of our favorite ones:
+ `obj?` - print short object info, including signature and docstring.
diff --git a/pythonetc/is-warning.md b/pythonetc/is-warning.md
index 5dafbaa..5499b92 100644
--- a/pythonetc/is-warning.md
+++ b/pythonetc/is-warning.md
@@ -1,3 +1,7 @@
+# warning about is
+
+Published: 16 March 2021, 18:00
+
Starting Python 3.8, the interpreter warns about `is` comparison of literals.
Python 3.7:
diff --git a/pythonetc/join-lists.md b/pythonetc/join-lists.md
index f2cb728..3b0ff6b 100644
--- a/pythonetc/join-lists.md
+++ b/pythonetc/join-lists.md
@@ -1,3 +1,7 @@
+# join lists
+
+Published: 11 March 2021, 18:00
+
Suppose, you have 10 lists:
```python
diff --git a/pythonetc/json-default.md b/pythonetc/json-default.md
index 23fd9d9..94f3d27 100644
--- a/pythonetc/json-default.md
+++ b/pythonetc/json-default.md
@@ -1,3 +1,6 @@
+# json default
+
+Published: 03 December 2020, 18:00
`json.dumps` can serialize every built-in type which has a corresponding JSON type (`int` as `number`, `None` as `null`, `list` as `array` etc) but fails for every other type. Probably, the most often case when you will face it is when trying to serialize a datetime object:
diff --git a/pythonetc/key-error.md b/pythonetc/key-error.md
index afdd1c9..eafad4a 100644
--- a/pythonetc/key-error.md
+++ b/pythonetc/key-error.md
@@ -1,3 +1,7 @@
+# KeyError
+
+Published: 15 April 2021, 18:00
+
Most of the exceptions raised from the standard library or built-ins have a quite descriptive self-contained message:
```python
diff --git a/pythonetc/license.md b/pythonetc/license.md
index f5946d7..5f5d030 100644
--- a/pythonetc/license.md
+++ b/pythonetc/license.md
@@ -1,3 +1,7 @@
+# license
+
+Published: 13 August 2020, 18:00
+
Python provides 2 useless but interesting built-in functions: `copyright` and `license`. `copyright` gives a short overview who owned Python in different moments of history:
```python
diff --git a/pythonetc/literal-eval.md b/pythonetc/literal-eval.md
index f350e33..67a36d3 100644
--- a/pythonetc/literal-eval.md
+++ b/pythonetc/literal-eval.md
@@ -1,3 +1,7 @@
+# ast.literal_eval
+
+Published: 25 August 2020, 18:00
+
`ast.literal_eval` is a restricted version of `eval` that evaluates only literals:
```python
diff --git a/pythonetc/log-extra.md b/pythonetc/log-extra.md
index f5e54f5..338afe5 100644
--- a/pythonetc/log-extra.md
+++ b/pythonetc/log-extra.md
@@ -7,16 +7,16 @@ logger.warning('user not found')
# user not found
```
-When this message is logged, it can be hard from it alone to reproduce the given situation, to understand what went wrong. So, it's good to provide some additional context. For example:
+When this message is logged, it can be hard based on it alone to reproduce the given situation, to understand what went wrong. So, it's good to provide some additional context. For example:
```python
user_id = 13
logger.warning(f'user #{user_id} not found')
```
-That's better, now we know what user it was. However, it's hard to work with such kind of messages. For example, we want to get notification when the same type of error messages occured too many times in a minute. Before, it was one error message, "user not found". Now, for every user we get a different message. Or another example, if we want to get all messages related to the same user. If we just search for "13", we will get many false-positives where "13" means something else, not user_id.
+That's better, now we know what user it was. However, it's hard to work with such kinds of messages. For example, we want to get a notification when the same type of error messages occurred too many times in a minute. Before, it was one error message, "user not found". Now, for every user, we get a different message. Or another example, if we want to get all messages related to the same user. If we just search for "13", we will get many false positives where "13" means something else, not user_id.
-The solution is to use [structured logging](softwareengineering.stackexchange.com/questions/312197/). The idea of structured logging is to store all additional values as separate fields instead of mixing everything in one text message. In Python, it can be achieved by passing the variables as `extra` argument. Most of the logging libraries will recognize and store everyting passed into `extra`. For example, how it looks like in [python-json-logger](https://pypi.org/project/python-json-logger/):
+The solution is to use [structured logging](softwareengineering.stackexchange.com/questions/312197/). The idea of structured logging is to store all additional values as separate fields instead of mixing everything in one text message. In Python, it can be achieved by passing the variables as the `extra` argument. Most of the logging libraries will recognize and store everything passed into `extra`. For example, how it looks like in [python-json-logger](https://pypi.org/project/python-json-logger/):
```python
from pythonjsonlogger import jsonlogger
@@ -40,7 +40,7 @@ logger.warning('user not found', extra=dict(user_id=13))
# user not found
```
-So, to show `extra` when printing human-readable log messages as a plain text, you have to write your own logs formatter:
+So, to show `extra` when printing human-readable log messages as plain text, you have to write your own logs formatter:
```python
import logging
diff --git a/pythonetc/lru-cache.md b/pythonetc/lru-cache.md
index 3647772..2f4a02c 100644
--- a/pythonetc/lru-cache.md
+++ b/pythonetc/lru-cache.md
@@ -1,3 +1,7 @@
+# functools.lru_cache
+
+Published: 15 December 2020, 18:00
+
Decorator [functools.lru_cache](https://docs.python.org/3/library/functools.html#functools.lru_cache) caches the function result based on the given arguments:
```python
diff --git a/pythonetc/magic.md b/pythonetc/magic.md
index 362799e..2e75205 100644
--- a/pythonetc/magic.md
+++ b/pythonetc/magic.md
@@ -1,3 +1,7 @@
+# don't use magic methods directly
+
+Published: 28 July 2020, 18:00
+
Try to avoid getting dunder attributes directly. Python provides helper functions for getting of of standard dunder attributes:
- `type(self)` instead of `self.__class__`
diff --git a/pythonetc/match.md b/pythonetc/match.md
index b045523..783be54 100644
--- a/pythonetc/match.md
+++ b/pythonetc/match.md
@@ -1,3 +1,7 @@
+# match
+
+Published: 26 June 2020, 18:00
+
On this Tuesday, a team of 5 authors (including Guido van Rossum) published [PEP-622](https://www.python.org/dev/peps/pep-0622/). This is a huge draft in terms of size, complexity, and impact. It is a proposal to extend Python syntax to support structural [pattern matching](https://en.wikipedia.org/wiki/Pattern_matching). Think about it as `if` statement on steroids.
A small example using `match` as [switch statement](https://en.wikipedia.org/wiki/Switch_statement):
diff --git a/pythonetc/nan.md b/pythonetc/nan.md
index 18dcd6b..8c31faf 100644
--- a/pythonetc/nan.md
+++ b/pythonetc/nan.md
@@ -1,3 +1,7 @@
+# nan
+
+Published: 01 September 2020, 18:00
+
Python has [NaN](https://t.me/pythonetc/561) float value and it's a rule-breaking thing:
```python
diff --git a/pythonetc/new-init.md b/pythonetc/new-init.md
index 2d8ce65..6e75f5d 100644
--- a/pythonetc/new-init.md
+++ b/pythonetc/new-init.md
@@ -1,7 +1,11 @@
+# `__new__` and `__init__`
+
+Published: 15 October 2020, 18:00
+
Creation of class instance is done by `__call__` method of `object` class (provided by metaclass `type`) and practically includes only 2 steps:
1. Call the `__new__` method to create an instance.
-2. Call the `__init__` method to set up the instance.
+1. Call the `__init__` method to set up the instance.
```python
class A:
@@ -24,7 +28,7 @@ A.__call__(1)
So, if you want to create an instance without executing `__init__`, just call `__new__`:
```python
-A.__new__(A, 1)
+A.__new__(A, 1)
# new (1,)
```
diff --git a/pythonetc/new-year.md b/pythonetc/new-year.md
index 718d477..3937e0b 100644
--- a/pythonetc/new-year.md
+++ b/pythonetc/new-year.md
@@ -1,3 +1,7 @@
+# new year
+
+Published: 31 December 2020, 18:00
+
```python
from base64 import b64decode
from random import choice
diff --git a/pythonetc/nonlocal.md b/pythonetc/nonlocal.md
index b5f6afd..cfc2bb4 100644
--- a/pythonetc/nonlocal.md
+++ b/pythonetc/nonlocal.md
@@ -1,3 +1,6 @@
+# nonlocal
+
+Published: 02 March 2021, 18:00
Any enclosing variable can be shadowed in the local scope without affecting the global one:
diff --git a/pythonetc/nullcontext.md b/pythonetc/nullcontext.md
index 36652bf..2c68b9a 100644
--- a/pythonetc/nullcontext.md
+++ b/pythonetc/nullcontext.md
@@ -1,3 +1,7 @@
+# contextlib.nullcontext
+
+Published: 01 October 2020, 18:00
+
Context manager [contextlib.nullcontext](https://docs.python.org/3/library/contextlib.html#contextlib.nullcontext) is helpful when a block of code not always should be executed in a context.
A good example is a function that works with a database. If a session is passed, the function will use it. Otherwise, it creates a new session, and does it in a context to guarantee fallback logic to be executed:
diff --git a/pythonetc/numbers.md b/pythonetc/numbers.md
index f784326..ccc725b 100644
--- a/pythonetc/numbers.md
+++ b/pythonetc/numbers.md
@@ -1,3 +1,7 @@
+# numbers (PEP-3141)
+
+Published: 22 September 2020, 18:00
+
Module [numbers](https://docs.python.org/3/library/numbers.html) was introduced by [PEP-3141](https://www.python.org/dev/peps/pep-3141/) in Python 2.6. It implements the numbers hierarchy, inspired by [Scheme](https://en.wikipedia.org/wiki/Scheme_programming_language):
```python
diff --git a/pythonetc/object-type.md b/pythonetc/object-type.md
index 030d5b0..ba76ad0 100644
--- a/pythonetc/object-type.md
+++ b/pythonetc/object-type.md
@@ -1,3 +1,7 @@
+# object and type
+
+Published: 10 September 2020, 18:00
+
Every class is an instance of its metaclass. The default metaclass is `type`. You can use this knowledge to check if something is a class or is an instance:
```python
diff --git a/pythonetc/objects.md b/pythonetc/objects.md
index 3caeead..feea294 100644
--- a/pythonetc/objects.md
+++ b/pythonetc/objects.md
@@ -1,3 +1,7 @@
+# everything is object
+
+Published: 15 September 2020, 18:00
+
Everything is an object, including functions, lambdas, and generators:
```python
diff --git a/pythonetc/prepare.md b/pythonetc/prepare.md
index 77172b5..d321dae 100644
--- a/pythonetc/prepare.md
+++ b/pythonetc/prepare.md
@@ -1,7 +1,11 @@
+# `__prepare__`
+
+Published: 09 July 2020, 18:00
+
Magic method `__prepare__` on metaclass is called on class creation. It must return a dict instance that then will be used as `__dict__` of the class. For example, it can be used to inject variables into the function scope:
```python
-class Meta(type):
+class Meta(type):
def __prepare__(_name, _bases, **kwargs):
d = {}
for k, v in kwargs.items():
diff --git a/pythonetc/pydoc.md b/pythonetc/pydoc.md
index da39391..20c9057 100644
--- a/pythonetc/pydoc.md
+++ b/pythonetc/pydoc.md
@@ -1,3 +1,7 @@
+# pydoc
+
+Published: 10 November 2020, 18:00
+
The script [pydoc](https://docs.python.org/3/library/pydoc.html) can be used to see documentationand docstrings from the console:
```bash
diff --git a/pythonetc/qualname.md b/pythonetc/qualname.md
index f73c4ee..60f7661 100644
--- a/pythonetc/qualname.md
+++ b/pythonetc/qualname.md
@@ -1,3 +1,7 @@
+# `__qualname__` (PEP-3155)
+
+Published: 24 November 2020, 18:00
+
In Python 3.3, [PEP-3155](https://www.python.org/dev/peps/pep-3155/) introduced a new `__qualname__` attribute for classes and functions which contains a full dotted path to the definition of the given object.
```python
diff --git a/pythonetc/re-compile.md b/pythonetc/re-compile.md
index 77e7aa2..9e8f382 100644
--- a/pythonetc/re-compile.md
+++ b/pythonetc/re-compile.md
@@ -1,3 +1,7 @@
+# re.compile
+
+Publish: 22 December 2020, 18:00
+
Always precompile regular expressions using `re.compile` if the expression is known in advance:
```python
diff --git a/pythonetc/recursion.md b/pythonetc/recursion.md
index c10f809..05d4219 100644
--- a/pythonetc/recursion.md
+++ b/pythonetc/recursion.md
@@ -1,3 +1,7 @@
+# sys.setrecursionlimit
+
+Published: 23 June 2020, 18:00
+
Python doesn't support [tail recursion](https://t.me/pythonetc/239). Hence, it's easy to face `RecursionError` when implementing recursive algorithms. You can get and change maximum recursion depth with [sys.getrecursionlimit](https://docs.python.org/3/library/sys.html#sys.getrecursionlimit) and [sys.setrecursionlimit](https://docs.python.org/3/library/sys.html#sys.setrecursionlimit) functions:
```python
diff --git a/pythonetc/scopes.md b/pythonetc/scopes.md
index 1b3348f..c968e57 100644
--- a/pythonetc/scopes.md
+++ b/pythonetc/scopes.md
@@ -1,3 +1,7 @@
+# scopes
+
+Published: 25 February 2021, 18:00
+
Let's talk a bit more about scopes.
Any class and function can implicitly use variables from the global scope:
diff --git a/pythonetc/season25.md b/pythonetc/season25.md
index ef13387..3a52e6a 100644
--- a/pythonetc/season25.md
+++ b/pythonetc/season25.md
@@ -1,3 +1,7 @@
+# Season #2.5
+
+Published: 24 February 2021, 16:20
+
It was a long break but tomorrow we start again. We have plenty of ideas for posts but don't always have time to write them. So, this is how you can help us:
+ If you have something to tell about Python (syntax, stdlib, PEPs), check if it already was posted. If not, write a post, send it to us, and we will publish it. It will include your name (if you want to), we don't steal content ;)
diff --git a/pythonetc/sentinel.md b/pythonetc/sentinel.md
index 35f7f79..aa4207e 100644
--- a/pythonetc/sentinel.md
+++ b/pythonetc/sentinel.md
@@ -1,3 +1,7 @@
+# unittest.mock.sentinel
+
+Published: 20 October 2020, 18:00
+
Some functions can accept as an argument value of any type or no value at all. If you set the default value to `None` you can't say if `None` was explicitly passed or not. For example, the [default value](https://docs.python.org/3/library/argparse.html#default) for [argparse.ArgumentParser.add_argument](https://docs.python.org/3/library/argparse.html#the-add-argument-method). For this purpose, you can create a new object and then use `is` check:
```python
diff --git a/pythonetc/set-name.md b/pythonetc/set-name.md
index e9406fd..95f5c31 100644
--- a/pythonetc/set-name.md
+++ b/pythonetc/set-name.md
@@ -1,3 +1,7 @@
+# `__set_name__` (PEP-487)
+
+Published: 21 July 2020, 18:00
+
If you're going to store data in the descriptor, the reasonable question is "where".
1. If data stored in the descriptor's attribute, it will be shared between all instances of the class where the descriptor is assigned.
diff --git a/pythonetc/simplenamespace.md b/pythonetc/simplenamespace.md
index e6357b4..ced9af3 100644
--- a/pythonetc/simplenamespace.md
+++ b/pythonetc/simplenamespace.md
@@ -1,3 +1,7 @@
+# types.SimpleNamespace
+
+Published: 24 September 2020, 18:00
+
[types.SimpleNamespace](https://docs.python.org/3/library/types.html#types.SimpleNamespace) is a way to make a `dict` with access by attributes:
```python
diff --git a/pythonetc/slots-docs.md b/pythonetc/slots-docs.md
index ee48ccd..5367857 100644
--- a/pythonetc/slots-docs.md
+++ b/pythonetc/slots-docs.md
@@ -1,3 +1,7 @@
+# dict as `__slots__`
+
+Published: 05 November 2020, 18:00
+
`__slots__` [can be used to save memory](https://t.me/pythonetc/233). You can use any iterable as `__slots__` value, including `dict`. AND Starting from Python 3.8, you can use `dict` to specify docstrings for slotted attributes `__slots__`:
```python
@@ -20,20 +24,20 @@ Also, `help(Channel)` lists docs for all slotted attributes:
```python
class Channel(builtins.object)
| Channel(slug, name)
- |
+ |
| Telegram channel
- |
+ |
| Methods defined here:
- |
+ |
| __init__(self, slug, name)
| Initialize self. See help(type(self)) for accurate signature.
- |
+ |
| ----------------------------------------------------------------------
| Data descriptors defined here:
- |
+ |
| name
| user-friendly name
- |
+ |
| slug
| short name, without @
```
diff --git a/pythonetc/snippets/f-strings.md b/pythonetc/snippets/f-strings.md
index 29e3cda..4f9cd04 100644
--- a/pythonetc/snippets/f-strings.md
+++ b/pythonetc/snippets/f-strings.md
@@ -1,3 +1,7 @@
+# f-strings
+
+Published: 25 June 2020, 18:00
+
You can implement [f-strings](https://www.python.org/dev/peps/pep-0498/) in older Python versions by accessing [globals and locals](https://t.me/pythonetc/121) from the caller function. It is possible through getting the parent frame from the call stack:
```python
diff --git a/pythonetc/snippets/final.md b/pythonetc/snippets/final.md
index d20d75f..53e319b 100644
--- a/pythonetc/snippets/final.md
+++ b/pythonetc/snippets/final.md
@@ -1,3 +1,7 @@
+# final
+
+Published: 06 August 2020, 18:00
+
Some languages, like Java, allow you to mark a class as `final` that means you can't inherit from it. There is how it can be implemented in a few lines (thanks to [Nikita Sobolev](https://github.com/sobolevn) for the implementation!):
```python
diff --git a/pythonetc/snippets/getitem.md b/pythonetc/snippets/getitem.md
index 4ebe4dd..cf9fb94 100644
--- a/pythonetc/snippets/getitem.md
+++ b/pythonetc/snippets/getitem.md
@@ -1,3 +1,7 @@
+# operator.getitem
+
+Published: 11 August 2020, 18:00
+
When you have a dict with a deep inheritance (like a configuration file) and path in it specified as a string, there is a fun and short way how to get a value from the dict by the given path:
```python
diff --git a/pythonetc/snippets/hamming.md b/pythonetc/snippets/hamming.md
index 48b0739..a23285c 100644
--- a/pythonetc/snippets/hamming.md
+++ b/pythonetc/snippets/hamming.md
@@ -1,3 +1,7 @@
+# hamming distance
+
+Published: 20 August 2020, 18:00
+
[Hamming distance](https://en.wikipedia.org/wiki/Hamming_distance) is the number of positions at which the corresponding symbols are different. It's the simplest measure of difference between 2 strings and can be implemented in a few lines:
```python
diff --git a/pythonetc/snippets/itertools.md b/pythonetc/snippets/itertools.md
index 60f8eec..e138cc3 100644
--- a/pythonetc/snippets/itertools.md
+++ b/pythonetc/snippets/itertools.md
@@ -1,3 +1,7 @@
+# itertools
+
+Published: 03 September 2020, 18:00
+
Some functional languages, like Elixir, have in the standard library a huge collection of functions to work with lazy enumerables (in Python, we name them [iterators](https://articles.orsinium.dev/python/iterators/)). In Python, this role is on [itertools](https://docs.python.org/3/library/itertools.html). However, `itertools` is a relatively small collection of such functions, it contains only most important and basic ones (maybe, a bit of junk, but so). The documentation has [Itertools Recipes](https://docs.python.org/3/library/itertools.html#itertools-recipes) with some useful functions. A few examples:
```python
diff --git a/pythonetc/snippets/sum-frames.md b/pythonetc/snippets/sum-frames.md
index 1c272cb..09d19f9 100644
--- a/pythonetc/snippets/sum-frames.md
+++ b/pythonetc/snippets/sum-frames.md
@@ -1,3 +1,7 @@
+# sum implemented on frames
+
+Published: 30 June 2020, 18:00
+
Let's have more fun with frames and recursion. There is sum function that adds 2 natural small numbers by getting down into recursive calls and then counting back the stack size:
```python
diff --git a/pythonetc/snippets/to-str-2.md b/pythonetc/snippets/to-str-2.md
index 45b2db3..d6bca68 100644
--- a/pythonetc/snippets/to-str-2.md
+++ b/pythonetc/snippets/to-str-2.md
@@ -1,3 +1,7 @@
+# int to str #2
+
+Published: 30 September 2020, 18:00
+
The point of the post above was that for some simple tasks there are many ways to do it (and some ways are good only in some cases). Also, the number of possible solutions grows as the language evolves. Another good example is concatenation. You can join 2 strings with f-strings, `str.format`, `str.join`, `+`, and so on. Thinking about these ways, even not suitable for daily usage, helps better language understanding.
Our amazing subscribers decided to take the challenge. Below are some not suitable for work but fan solutions how to convert int to str.
diff --git a/pythonetc/snippets/to-str.md b/pythonetc/snippets/to-str.md
index e84dd98..ac18e4f 100644
--- a/pythonetc/snippets/to-str.md
+++ b/pythonetc/snippets/to-str.md
@@ -1,3 +1,7 @@
+# int to str
+
+Published: 29 September 2020, 18:00
+
How many ways you know how to convert `int` to `str`? Let's try! Note that complications of the same method don't count.
```python
diff --git a/pythonetc/str-append.md b/pythonetc/str-append.md
index 7f5de8c..ecd8839 100644
--- a/pythonetc/str-append.md
+++ b/pythonetc/str-append.md
@@ -1,3 +1,7 @@
+# join strings
+
+Published: 29 December 2020, 18:00
+
What is the fastest way to build a string from many substrings in a loop? In other words, how to concatenate fast when we don't know in advance how many strings we have? There are many discussions about it, and the common advice is that strings are immutable, so it's better to use a list and then `str.join` it. Let's not trust anyone and just check it.
The straightforward solution:
diff --git a/pythonetc/str-concat.md b/pythonetc/str-concat.md
index af3cd60..300a5a0 100644
--- a/pythonetc/str-concat.md
+++ b/pythonetc/str-concat.md
@@ -1,3 +1,7 @@
+# int to str performance
+
+Published: 04 March 2021, 18:00
+
Let's learn a bit more about strings performance. What if instead of an unknown amount of strings we have only a few known variables?
```python
diff --git a/pythonetc/sys-modules.md b/pythonetc/sys-modules.md
index 629b052..c4fc370 100644
--- a/pythonetc/sys-modules.md
+++ b/pythonetc/sys-modules.md
@@ -1,3 +1,7 @@
+# sys.modules
+
+Published: 17 September 2020, 18:00
+
Python caches every imported module is `sys.modules`:
```python
diff --git a/pythonetc/tau.md b/pythonetc/tau.md
index b2618ec..5e20284 100644
--- a/pythonetc/tau.md
+++ b/pythonetc/tau.md
@@ -1,3 +1,7 @@
+# math.tau (PEP-628)
+
+Published: 24 December 2020, 18:00
+
The issue with a beautiful number [#12345](https://bugs.python.org/issue12345) proposed to add the following constant into stdlib:
```python
diff --git a/pythonetc/typed-dict.md b/pythonetc/typed-dict.md
index efaca41..8b2ba07 100644
--- a/pythonetc/typed-dict.md
+++ b/pythonetc/typed-dict.md
@@ -1,3 +1,7 @@
+# typing.TypedDict (PEP-589)
+
+Published: 25 March 2021, 18:00
+
[PEP-589](https://www.python.org/dev/peps/pep-0589/) (landed in Python 3.8) introduced `typing.TypedDict` as a way to annotate dicts:
```python
diff --git a/pythonetc/yield-compr.md b/pythonetc/yield-compr.md
index 8f6126f..ce65d77 100644
--- a/pythonetc/yield-compr.md
+++ b/pythonetc/yield-compr.md
@@ -1,3 +1,7 @@
+# yield and comprehensions
+
+Published: 22 October 2020, 18:00
+
Accidentally, `yield` can be used in generator expressions and comprehensions:
```python
@@ -14,7 +18,7 @@ list((yield i) for i in 'ab')
This is because `yield` can be used in any function (turning it into a generator) and comprehensions are compiled into functions:
```python
->>> dis.dis("[(yield i) for i in range(3)]")
+>>> dis.dis("[(yield i) for i in range(3)]")
0 LOAD_CONST 0 ( ...>)
2 LOAD_CONST 1 ('')
4 MAKE_FUNCTION 0
diff --git a/pythonetc/zen.md b/pythonetc/zen.md
index 2506ea2..7929e62 100644
--- a/pythonetc/zen.md
+++ b/pythonetc/zen.md
@@ -1,3 +1,7 @@
+# zen of python (PEP-20)
+
+Published: 27 August 2020, 18:00
+
The famous "Zen of Python" was introduced in [PEP-20](https://www.python.org/dev/peps/pep-0020/). This is 19 aphorisms [authored by Tim Peters](https://mail.python.org/pipermail/python-list/1999-June/001951.html). Do `import this` in the Python interpreter to see them:
```python
@@ -27,7 +31,6 @@ Namespaces are one honking great idea -- let's do more of those!
The fun thing is how this module looks like. The original text is encoded by [ROT13](https://en.wikipedia.org/wiki/ROT13) algorithm and is decoded on the fly:
-
```python
s = """Gur Mra bs Clguba, ol Gvz Crgref
...
diff --git a/pythonetc/zipapp.md b/pythonetc/zipapp.md
index a09cb38..d473d23 100644
--- a/pythonetc/zipapp.md
+++ b/pythonetc/zipapp.md
@@ -1,9 +1,13 @@
+# zipapp
+
+Published: 13 October 2020, 18:00
+
The module [zipapp](https://docs.python.org/3/library/zipapp.html) can pack a python module into a zip archive that can be executed directly by a Python interpreter. It is a good way to ship CLI tools:
```bash
$ mkdir example
$ echo 'print("hello, @pythonetc!")' > example/__main__.py
$ python3 -m zipapp example
-$ python3 example.pyz
+$ python3 example.pyz
hello, @pythonetc!
```