en
Feedback
Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Python Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° | Книги ΠΏΠΎ ΠΏΠΈΡ‚ΠΎΠ½Ρƒ

Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Python Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° | Книги ΠΏΠΎ ΠΏΠΈΡ‚ΠΎΠ½Ρƒ

Open in Telegram

ΠŸΠΎΠ³Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ Π² CPython ΠΈ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ. Π Π°Π·Π±ΠΈΡ€Π°Π΅ΠΌ Π½Π΅ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ (GIL, Memory), Best Practices (SOLID, DDD) ΠΈ тонкости Django/FastAPI. РСшаСм Π·Π°Π΄Π°Ρ‡ΠΈ с ΠΏΠΎΠ΄Π²ΠΎΡ…ΠΎΠΌ ΠΈ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΡ‹. 🐍 По всСм вопросам @evgenycarter РКН clck.ru/3Ko7Hq

Show more

πŸ“ˆ Analytical overview of Telegram channel Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Python Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° | Книги ΠΏΠΎ ΠΏΠΈΡ‚ΠΎΠ½Ρƒ

Channel Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Python Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° | Книги ΠΏΠΎ ΠΏΠΈΡ‚ΠΎΠ½Ρƒ (@bookpython) in the Russian language segment is an active participant. Currently, the community unites 18 126 subscribers, ranking 7 029 in the Technologies & Applications category and 36 294 in the Russia region.

πŸ“Š Audience metrics and dynamics

Since its creation on Π½Π΅Π²Ρ–Π΄ΠΎΠΌΠΎ, the project has demonstrated rapid growth, gathering an audience of 18 126 subscribers.

According to the latest data from 26 August, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by -69 over the last 30 days and by 1 over the last 24 hours, overall reach remains high.

  • Verification status: Not verified
  • Engagement rate (ER): The average audience engagement rate is 5.49%. Within the first 24 hours after publication, content typically collects 2.59% reactions from the total number of subscribers.
  • Post reach: On average, each post receives 995 views. Within the first day, a publication typically gains 469 views.
  • Reactions and interaction: The audience actively supports content: the average number of reactions per post is 3.
  • Thematic interests: Content is focused on key topics such as numbers, yield, ΠΌΠΎΠ΄ΡƒΠ»ΡŒ, none, Π΄Π΅ΠΊΠΎΡ€Π°Ρ‚ΠΎΡ€.

πŸ“ Description and content policy

The author describes the resource as a platform for expressing subjective opinions:
β€œΠŸΠΎΠ³Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ Π² CPython ΠΈ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ. Π Π°Π·Π±ΠΈΡ€Π°Π΅ΠΌ Π½Π΅ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ (GIL, Memory), Best Practices (SOLID, DDD) ΠΈ тонкости Django/FastAPI. РСшаСм Π·Π°Π΄Π°Ρ‡ΠΈ с ΠΏΠΎΠ΄Π²ΠΎΡ…ΠΎΠΌ ΠΈ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΡ‹. 🐍 По всСм вопросам @evgenycarter РКН clck.ru/3Ko7Hq”

Thanks to the high frequency of updates (latest data received on 27 August, 2026), the channel maintains relevance and a high level of publication reach. Analytics show that the audience actively interacts with content, making it an important point of influence in the Technologies & Applications category.

18 126
Subscribers
+124 hours
-297 days
-6930 days
Posts Archive
ВстроСнныС значСния float Π² Python ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ ΠΎΠ±ΠΎΡ€ΡƒΠ΄ΠΎΠ²Π°Π½ΠΈΠ΅ вашСго ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π° Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ, поэтому любоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ прСдставляСтся Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅ Π² Π²ΠΈΠ΄Π΅ Π΄Π²ΠΎΠΈΡ‡Π½ΠΎΠΉ Π΄Ρ€ΠΎΠ±ΠΈ. Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π²Ρ‹ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚Π΅ с приблиТСниями, Π° Π½Π΅ с Ρ‚ΠΎΡ‡Π½Ρ‹ΠΌΠΈ значСниями:

>>> format(0.1, '.17f')
'0.10000000000000001'
ΠœΠΎΠ΄ΡƒΠ»ΡŒ decimal позволяСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΄Π΅ΡΡΡ‚ΠΈΡ‡Π½ΡƒΡŽ Π°Ρ€ΠΈΡ„ΠΌΠ΅Ρ‚ΠΈΠΊΡƒ с ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½ΠΎΠΉ Ρ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒΡŽ:

>>> from decimal import Decimal
>>> Decimal(1) / Decimal(3)
Decimal('0.3333333333333333333333333333')
Но ΠΈ этого ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ нСдостаточно:

>>> Decimal(1) / Decimal(3) * Decimal(3) == Decimal(1)
False
Для Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½ΠΎ Ρ‚ΠΎΡ‡Π½Ρ‹Ρ… вычислСний ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ fractions, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ…Ρ€Π°Π½ΠΈΡ‚ любоС число ΠΊΠ°ΠΊ Ρ€Π°Ρ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠ΅:

>>> from fractions import Fraction
>>> Fraction(1) / Fraction(3) * Fraction(3) == Fraction(1)
True
ΠžΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎΠ΅ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ β€” всё Ρ€Π°Π²Π½ΠΎ приходится ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ приблиТСния для ΠΈΡ€Ρ€Π°Ρ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹Ρ… чисСл, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ Ο€. πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Π² Python Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π΄Π²Π° ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Ρ… этапа. Π‘Π½Π°Ρ‡Π°Π»Π° вызываСтся ΠΌΠ΅Ρ‚ΠΎΠ΄ __new__, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ создаёт ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½ΠΎΠ²Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚. Π—Π°Ρ‚Π΅ΠΌ вызываСтся ΠΌΠ΅Ρ‚ΠΎΠ΄ __init__ для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ состояния этого ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Однако, Ссли __new__ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π½Π΅ являСтся экзСмпляром исходного класса, ΠΌΠ΅Ρ‚ΠΎΠ΄ __init__ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½. Π­Ρ‚ΠΎ связано с Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, вСроятно, ΡƒΠΆΠ΅ создан Π΄Ρ€ΡƒΠ³ΠΈΠΌ классом, ΠΈ Π΅Π³ΠΎ __init__ ΡƒΠΆΠ΅ Π±Ρ‹Π» Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½:

class Foo:
    def __new__(cls, x):
        return dict(x=x)

    def __init__(self, x):
        print(x)  # Никогда Π½Π΅ вызываСтся

print(Foo(0))
Π’Π°ΠΆΠ½ΠΎ: Π½Π΅ слСдуСт ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ экзСмпляры Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ класса Π² __new__ с использованиСм ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ³ΠΎ конструктора (Foo(...)). Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π΄Π²ΠΎΠΉΠ½ΠΎΠΌΡƒ Π²Ρ‹Π·ΠΎΠ²Ρƒ __init__ ΠΈΠ»ΠΈ Π΄Π°ΠΆΠ΅ ΠΊ бСсконСчной рСкурсии. ΠŸΡ€ΠΈΠΌΠ΅Ρ€ бСсконСчной рСкурсии:

class Foo:
    def __new__(cls, x):
        return Foo(-x)  # РСкурсия
ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π΄Π²ΠΎΠΉΠ½ΠΎΠ³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π° __init__:

class Foo:
    def __new__(cls, x):
        if x < 0:
            return Foo(-x)
        return super().__new__(cls)

    def __init__(self, x):
        print(x)
        self._x = x
ΠŸΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ способ:

class Foo:
    def __new__(cls, x):
        if x < 0:
            return cls.__new__(cls, -x)
        return super().__new__(cls)

    def __init__(self, x):
        print(x)
        self._x = x
πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

πŸš€ ΠŸΠΎΠ΄Π±ΠΎΡ€ΠΊΠ° ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Ρ… IT ΠΊΠ°Π½Π°Π»ΠΎΠ² Π² Max БистСмноС администрированиС, DevOps πŸ“Œ https://max.ru/i_odmin ВсС для систСмного администратора https://max.ru/bash_srv Bash Π‘ΠΎΠ²Π΅Ρ‚Ρ‹ https://max.ru/sysadminof Книги для Π°Π΄ΠΌΠΈΠ½ΠΎΠ², ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Π΅ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹ https://max.ru/i_odmin_book Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° БистСмного Администратора https://max.ru/i_devops DevOps: ПишСм ΠΎ Docker, Kubernetes ΠΈ Π΄Ρ€. 1C Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° πŸ“Œ https://max.ru/odin1c_rus CΡ‚Π°Ρ‚ΡŒΠΈ, курсы, совСты, ΡˆΠ°Π±Π»ΠΎΠ½Ρ‹ ΠΊΠΎΠ΄Π° 1Π‘ ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ C++πŸ“Œ https://max.ru/cpp_lib Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° C/C++ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Python πŸ“Œ https://max.ru/python_of Python акадСмия. https://max.ru/BookPython Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Python Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° Java Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° πŸ“Œ https://max.ru/bookjava Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Java Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° GitHub БообщСство πŸ“Œ https://max.ru/githublib Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½ΠΎΠ΅ ΠΈΠ· GitHub Π‘Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… (Data Base) πŸ“Œ https://max.ru/database_info ВсС ΠΏΡ€ΠΎ Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Π€Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° πŸ“Œ https://max.ru/frontend_1 ΠŸΠΎΠ΄Π±ΠΎΡ€ΠΊΠΈ для frontend Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ πŸ“Œ https://max.ru/programmist_of Книги ΠΏΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ https://max.ru/proglb Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста https://max.ru/bfbook Книги для программистов ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ πŸ“Œ https://max.ru/bookflow Π›Π΅ΠΊΡ†ΠΈΠΈ, Π²ΠΈΠ΄Π΅ΠΎΡƒΡ€ΠΎΠΊΠΈ, Π΄ΠΎΠΊΠ»Π°Π΄Ρ‹ с IT ΠΊΠΎΠ½Ρ„Π΅Ρ€Π΅Π½Ρ†ΠΈΠΉ https://max.ru/itmozg ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡΡ‚Ρ‹, Π΄ΠΈΠ·Π°ΠΉΠ½Π΅Ρ€Ρ‹, новости ΠΈΠ· ΠΌΠΈΡ€Π° IT https://max.ru/php_lib Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° PHP программиста πŸ‘¨πŸΌβ€πŸ’»πŸ‘©β€πŸ’» Π¨ΡƒΡ‚ΠΊΠΈ программистов πŸ“Œ https://max.ru/itumor Π¨ΡƒΡ‚ΠΊΠΈ программистов Π—Π°Ρ‰ΠΈΡ‚Π°, Π²Π·Π»ΠΎΠΌ, Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ πŸ“Œ https://max.ru/thehaking Канал ΠΎ кибСрбСзопасности https://max.ru/xakkep_1 Π₯Π°ΠΊΠ΅Ρ€ Free Книги, ΡΡ‚Π°Ρ‚ΡŒΠΈ для Π΄ΠΈΠ·Π°ΠΉΠ½Π΅Ρ€ΠΎΠ² πŸ“Œ https://max.ru/odesigners Π‘Ρ‚Π°Ρ‚ΡŒΠΈ, ΠΊΠ½ΠΈΠ³ΠΈ для Π΄ΠΈΠ·Π°ΠΉΠ½Π΅Ρ€ΠΎΠ² ΠœΠ°Ρ‚Π΅ΠΌΠ°Ρ‚ΠΈΠΊΠ° πŸ“Œ https://max.ru/Pomatematike Канал ΠΏΠΎ ΠΌΠ°Ρ‚Π΅ΠΌΠ°Ρ‚ΠΈΠΊΠ΅ https://max.ru/phismat_1 ΠžΠ±ΡƒΡ‡Π°ΡŽΡ‰ΠΈΠ΅ Π²ΠΈΠ΄Π΅ΠΎ, ΠΊΠ½ΠΈΠ³ΠΈ ΠΏΠΎ Π€ΠΈΠ·ΠΈΠΊΠ΅ ΠΈ ΠœΠ°Ρ‚Π΅ΠΌΠ°Ρ‚ΠΈΠΊΠ΅ Вакансии πŸ“Œ https://max.ru/progjob Вакансии Π² IT ΠœΠΈΡ€ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ πŸ“Œ https://max.ru/mir_teh Канал для Π»ΡŽΠ±ΠΎΠ·Π½Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… Бонус πŸ“Œ https://max.ru/piterspb_78 Π‘Π²Π΅ΠΆΠΈΠ΅ новости Π‘Π°Π½ΠΊΡ‚-ΠŸΠ΅Ρ‚Π΅Ρ€Π±ΡƒΡ€Π³Π° https://max.ru/mockva_life Π‘Π²Π΅ΠΆΠΈΠ΅ новости ΠœΠΎΡΠΊΠ²Ρ‹

Как ΡƒΠΏΡ€ΠΎΡΡ‚ΠΈΡ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ с Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°ΠΌΠΈ Π² ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строкС с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ typer РаньшС для CLI-ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ Π½Π° Python я использовал argparse, ΠΏΠΎΡ‚ΠΎΠΌ Π±Ρ‹Π» click, Π½ΠΎ Π½Π΅Π΄Π°Π²Π½ΠΎ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ ΠΏΠ΅Ρ€Π΅ΡˆΡ‘Π» Π½Π° typer. Π­Ρ‚ΠΎ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° ΠΎΡ‚ Π°Π²Ρ‚ΠΎΡ€Π° FastAPI, ΠΈ ΠΎΠ½Π° Ρ€Π΅Π°Π»ΡŒΠ½ΠΎ πŸ”₯ Π’ΠΎΡ‚ простой ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

import typer

app = typer.Typer()

@app.command()
def hello(name: str, age: int = 18):
    print(f"ΠŸΡ€ΠΈΠ²Π΅Ρ‚, {name}! Π’Π΅Π±Π΅ {age} Π»Π΅Ρ‚.")

if __name__ == "__main__":
    app()
Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ Π² Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Π»Π΅:

$ python main.py hello Alice --age 30
ΠŸΡ€ΠΈΠ²Π΅Ρ‚, Alice! Π’Π΅Π±Π΅ 30 Π»Π΅Ρ‚.
Π§Ρ‚ΠΎ ΠΊΡ€ΡƒΡ‚ΠΎ: - АвтоматичСски гСнСрируСтся --help - ΠŸΠΈΡˆΠ΅Ρ‚ΡΡ ΠΏΠΎΡ‡Ρ‚ΠΈ ΠΊΠ°ΠΊ обычная функция - Π•ΡΡ‚ΡŒ Π°Π²Ρ‚ΠΎΠΊΠΎΠΌΠΏΠ»ΠΈΡ‚ Π² ΠΎΠ±ΠΎΠ»ΠΎΡ‡ΠΊΠ°Ρ… (bash/zsh) - ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° Π°Π½Π½ΠΎΡ‚Π°Ρ†ΠΈΠΉ Ρ‚ΠΈΠΏΠΎΠ² ΠΈ Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ "ΠΈΠ· ΠΊΠΎΡ€ΠΎΠ±ΠΊΠΈ" Если Ρ‚Ρ‹ всё Π΅Ρ‰Ρ‘ ΡΡ‚Ρ€Π°Π΄Π°Π΅ΡˆΡŒ с argparse, Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΡŽ ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ typer. ОсобСнно Ссли Ρ‚Ρ‹ ΡƒΠΆΠ΅ ΠΊΠ°ΠΉΡ„ΡƒΠ΅ΡˆΡŒ ΠΎΡ‚ FastAPI β€” синтаксис ΠΈ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ ΠΎΡ‡Π΅Π½ΡŒ ΠΏΠΎΡ…ΠΎΠΆΠΈ. πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

ΠŸΠΎΠΏΡƒΠ»ΡΡ€Π½Ρ‹ΠΉ способ ΠΎΠ±ΡŠΡΠ²ΠΈΡ‚ΡŒ абстрактный ΠΌΠ΅Ρ‚ΠΎΠ΄ Π² Python β€” это Π²Ρ‹Π±Ρ€ΠΎΡΠΈΡ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ NotImplementedError:

def human_name(self):
    raise NotImplementedError
Π₯отя этот ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ довольно распространён ΠΈ Π΄Π°ΠΆΠ΅ поддСрТиваСтся IDE (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, PyCharm считаСт Ρ‚Π°ΠΊΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ абстрактными), Ρƒ Π½Π΅Π³ΠΎ Π΅ΡΡ‚ΡŒ нСдостаток: ошибка Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°, Π° Π½Π΅ ΠΏΡ€ΠΈ создании экзСмпляра класса. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ этой ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ abc:

from abc import ABCMeta, abstractmethod

class Service(metaclass=ABCMeta):
    @abstractmethod
    def human_name(self):
        pass
Π’Π°ΠΊΠΆΠ΅ Π²Π°ΠΆΠ½ΠΎ ΠΏΠΎΠΌΠ½ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ NotImplemented β€” это Π½Π΅ Ρ‚ΠΎ ΠΆΠ΅ самоС, Ρ‡Ρ‚ΠΎ NotImplementedError. NotImplemented β€” это ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ (ΠΊΠ°ΠΊ True ΠΈ False), Π° Π½Π΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅. Оно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΌΠ΅Ρ‚ΠΎΠ΄Π°Ρ… (__eq__(), __add__() ΠΈ Π΄Ρ€.), Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠΎΠ±Ρ‰ΠΈΡ‚ΡŒ Python, Ρ‡Ρ‚ΠΎ опСрация Π½Π΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° для Π΄Π°Π½Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°, ΠΈ ΠΏΠΎΠΏΡ‹Ρ‚Π°Ρ‚ΡŒΡΡ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ссли a.__add__(b) Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ NotImplemented, Python ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅Ρ‚ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ b.__radd__(a)). πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚ΡΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ ΠΏΠΎ Π΅Π³ΠΎ значСниям, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ sorted с ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ ΠΊΠ»ΡŽΡ‡Π°:

>>> d = dict(a=1, c=3, b=2)
>>> sorted(d.items(), key=lambda item: item[1])
[('a', 1), ('b', 2), ('c', 3)]
Однако такая функция ΡƒΠΆΠ΅ сущСствуСт Π² ΠΌΠΎΠ΄ΡƒΠ»Π΅ operator:

>>> from operator import itemgetter
>>> sorted(d.items(), key=itemgetter(1))
[('a', 1), ('b', 2), ('c', 3)]
Π’Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠ»ΡŽΡ‡ΠΈ вмСсто ΠΏΠ°Ρ€ ΠΊΠ»ΡŽΡ‡-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅:

>>> sorted(d, key=lambda k: d[k])
['a', 'b', 'c']
И снова, эту лямбду ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ ΡƒΠΆΠ΅ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ:

>>> sorted(d, key=d.get)
['a', 'b', 'c']
πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

НСкоторый ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ΡŒ ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΡƒΡŽΡ‰ΠΈΠ΅ вас Π΄Π°Π½Π½Ρ‹Π΅ Π² stdout, вмСсто Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡ‚ΡŒ API, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‰ΠΈΠΉ строку, ΠΏΡ€ΠΈΠ³ΠΎΠ΄Π½ΡƒΡŽ для использования Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅. ВмСсто Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³Π° Ρ‚Π°ΠΊΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π° ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€ΠΎΠΌ контСкста contextlib.redirect_stdout, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ позволяСт Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΠΏΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ stdout Π² любой ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‰ΠΈΠΉ Ρ„Π°ΠΉΠ»ΠΎΠ²Ρ‹ΠΉ интСрфСйс. Π’ сочСтании с io.StringIO это позволяСт ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ Π²Ρ‹Π²ΠΎΠ΄ Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ.

from contextlib import redirect_stdout
from io import StringIO

s = StringIO()
with redirect_stdout(s):
    print(42)

print(s.getvalue())
Π’Π°ΠΊΠΆΠ΅ сущСствуСт contextlib.redirect_stderr для пСрСнаправлСния Π²Ρ‹Π²ΠΎΠ΄Π° sys.stderr. πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

Иногда Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ Π½ΡƒΠΆΠ½Π° ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ β€” ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€, ΠΊΡƒΠ΄Π° элСмСнты Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ с ΠΎΠ΄Π½ΠΎΠΉ стороны ΠΈ ΠΈΠ·Π²Π»Π΅ΠΊΠ°ΡŽΡ‚ΡΡ с Π΄Ρ€ΡƒΠ³ΠΎΠΉ. Π’ Python для этого ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ list:

In : lst = [1, 2, 3]
In : lst.pop()
Out: 3
In : lst
Out: [1, 2]
In : lst[:0] = [4]  # push
In : lst
Out: [4, 1, 2]
Однако list выглядит Π½Π΅ ΠΎΡ‡Π΅Π½ΡŒ ΡƒΠ΄ΠΎΠ±Π½ΠΎ (взглянитС Π½Π° этот "push") ΠΈ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ нСэффСктивно.

In : lst = [0] * 10_000_000

In : %timeit lst[:0] = [1]
9.5 ms Β± 111 Β΅s per loop (mean Β± std. dev. of 7 runs, 100 loops each)

In : %timeit lst.pop()
84.3 ns Β± 4.01 ns per loop (mean Β± std. dev. of 7 runs, 10000000 loops each)
Как Π²ΠΈΠ΄Π½ΠΎ, опСрация pop() Π² 100 Ρ€Π°Π· быстрСС, Ρ‡Π΅ΠΌ вставка Π² Π½Π°Ρ‡Π°Π»ΠΎ списка. Π­Ρ‚ΠΎ связано с Ρ‚Π΅ΠΌ, ΠΊΠ°ΠΊ устроСн list Π² Python: Π»Π΅Π³ΠΊΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ ΠΈ ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ элСмСнты с ΠΊΠΎΠ½Ρ†Π°, Π½ΠΎ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅/Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π² Π½Π°Ρ‡Π°Π»ΠΎ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ создания Π½ΠΎΠ²ΠΎΠ³ΠΎ списка. Для ΠΎΡ‡Π΅Ρ€Π΅Π΄Π΅ΠΉ Π»ΡƒΡ‡ΡˆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ collections.deque. Он ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ для этого создан:

In : from collections import deque
In : d = deque([1] * 100_000_000)
In : %timeit d.popleft()
65 ns Β± 0.436 ns per loop (mean Β± std. dev. of 7 runs, 10000000 loops each)
πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

Π‘ΠΊΡ€Ρ‹Ρ‚Ρ‹Π΅ Ρ„ΠΈΡ‡ΠΈ Enum: ΠΊΠ°ΠΊ Π²Ρ‹ΠΆΠ°Ρ‚ΡŒ максимум МногиС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ Enum ΠΊΠ°ΠΊ простой список констант. Но Ρƒ enum.Enum Π² Python Π΅ΡΡ‚ΡŒ ΠΊΡƒΠ΄Π° большС возмоТностСй β€” ΠΈ ΠΎΠ½ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΊΠΎΠ΄ Ρ‡ΠΈΡ‰Π΅ ΠΈ ΠΌΠΎΡ‰Π½Π΅Π΅. Π’ΠΎΡ‚ нСсколько ΠΏΡ€ΠΈΡ‘ΠΌΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠ°Π»ΠΎ ΠΊΡ‚ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ β€” Π½ΠΎ зря. 1. Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ повСдСния Π² Enum

from enum import Enum

class Status(Enum):
    DRAFT = 'draft'
    PUBLISHED = 'published'
    ARCHIVED = 'archived'

    def is_visible(self):
        return self in {Status.DRAFT, Status.PUBLISHED}
Π’Π΅ΠΏΠ΅Ρ€ΡŒ Status.DRAFT.is_visible() β€” это просто ΠΈ элСгантно. 2. Enum с полями

from enum import Enum

class Color(Enum):
    RED = ('#FF0000', 'danger')
    GREEN = ('#00FF00', 'safe')

    def __init__(self, hex_code, label):
        self.hex_code = hex_code
        self.label = label

Color.RED.hex_code  # '#FF0000'
Color.RED.label     # 'danger'
3. АвтоматичСскиС значСния с auto()

from enum import Enum, auto

class Role(Enum):
    ADMIN = auto()
    USER = auto()
    GUEST = auto()
Π£Π΄ΠΎΠ±Π½ΠΎ, Ссли Π½Π΅ Π²Π°ΠΆΠ½Ρ‹ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹Π΅ значСния, Π° Π½ΡƒΠΆΠ½Ρ‹ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅. 4. Бтрогая сСриализация Π’ Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Ρ… прилоТСниях (API, Π±Π°Π·Ρ‹) Π»ΡƒΡ‡ΡˆΠ΅ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΡΠ΅Ρ€ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ enum'ΠΎΠ²:

import json

class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Enum):
            return obj.value
        return super().default(obj)

json.dumps(Status.PUBLISHED, cls=CustomEncoder)  # "published"
5. Π‘Ρ€Π°Π²Π½Π΅Π½ΠΈΠ΅ ΠΏΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΡŽ

Status('draft') == Status.DRAFT  # True
Status('draft') is Status.DRAFT  # True (enum Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ singleton)
Π˜Ρ‚ΠΎΠ³ΠΎ: Enum β€” это Π½Π΅ просто константы. Π­Ρ‚ΠΎ Π»Ρ‘Π³ΠΊΠΈΠΉ способ ΠΈΠ½ΠΊΠ°ΠΏΡΡƒΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΈ Π΄Π°Π½Π½Ρ‹Π΅, ΡƒΠ»ΡƒΡ‡ΡˆΠΈΡ‚ΡŒ Ρ‡ΠΈΡ‚Π°Π΅ΠΌΠΎΡΡ‚ΡŒ ΠΈ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΊΠΎΠ΄ устойчивСС ΠΊ ошибкам. πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

Π‘Ρ‚Π°Π½Π΄Π°Ρ€Ρ‚Π½Ρ‹ΠΉ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ json ΠΈΠΌΠ΅Π΅Ρ‚ интСрфСйс ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ»Π΅Π·Π΅Π½ для форматирования JSON ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ срСдствами Python. ΠœΠΎΠ΄ΡƒΠ»ΡŒ называСтся json.tool ΠΈ вызываСтся ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

$ echo '{"a": [], "b": "c"}' | python -m json.tool
{
    "a": [],
    "b": "c"
}
πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

default_factory Π² dataclass: ΠΌΠΎΡ‰Π½Π΅Π΅, Ρ‡Π΅ΠΌ каТСтся МногиС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ dataclass ΠΊΠ°ΠΊ ΡƒΠ΄ΠΎΠ±Π½Ρ‹ΠΉ способ Π·Π°Π΄Π°Ρ‚ΡŒ структуру с полями. Но Ρ€Π΅Π΄ΠΊΠΎ ΠΊΡ‚ΠΎ ΠΏΠΎ-настоящСму раскрываСт силу default_factory. А зря β€” ΠΎΠ½ спасаСт ΠΎΡ‚ Π±Π°Π³ΠΎΠ² ΠΈ Π΄Π°Ρ‘Ρ‚ Π³ΠΈΠ±ΠΊΠΎΡΡ‚ΡŒ. Когда Π½ΡƒΠΆΠ½ΠΎ Π·Π°Π΄Π°Ρ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для поля Π² dataclass, Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ Ρ‚ΡΠ½ΡƒΡ‚ΡŒΡΡ ΠΊ default=. Но Ссли это измСняСмый Ρ‚ΠΈΠΏ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, список ΠΈΠ»ΠΈ ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ) β€” вас ΠΏΠΎΠ΄ΠΆΠΈΠ΄Π°Π΅Ρ‚ Π»ΠΎΠ²ΡƒΡˆΠΊΠ°.

from dataclasses import dataclass, field

@dataclass
class User:
    name: str
    tags: list[str] = []  # ⚠️ опасно!
ВсС экзСмпляры User Π±ΡƒΠ΄ΡƒΡ‚ Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΎΠ΄ΠΈΠ½ ΠΈ Ρ‚ΠΎΡ‚ ΠΆΠ΅ список. Π’ΠΎ Π΅ΡΡ‚ΡŒ:

a = User("Alice")
b = User("Bob")
a.tags.append("admin")

print(b.tags)  # ['admin'] 😱
ВмСсто этого ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ default_factory:

@dataclass
class User:
    name: str
    tags: list[str] = field(default_factory=list)
Π’Π΅ΠΏΠ΅Ρ€ΡŒ Ρƒ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ User Π±ΡƒΠ΄Π΅Ρ‚ свой список:

a = User("Alice")
b = User("Bob")
a.tags.append("admin")

print(b.tags)  # []
Но default_factory Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΎ списки. Π­Ρ‚ΠΎ ΠΎΡ‚Π»ΠΈΡ‡Π½Ρ‹ΠΉ способ Π·Π°Π΄Π°Ρ‚ΡŒ любоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ "ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ", Π²ΠΊΠ»ΡŽΡ‡Π°Ρ ΠΊΠ°ΡΡ‚ΠΎΠΌΠ½ΡƒΡŽ Π»ΠΎΠ³ΠΈΠΊΡƒ:

import uuid

@dataclass
class Session:
    id: str = field(default_factory=lambda: str(uuid.uuid4()))
Или, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, значСния ΠΈΠ· окруТСния:

import os

@dataclass
class Config:
    debug: bool = field(default_factory=lambda: os.getenv("DEBUG") == "1")
ΠšΡΡ‚Π°Ρ‚ΠΈ, это Π΅Ρ‰Ρ‘ ΠΈ ΠΎΡ‚Π»ΠΈΡ‡Π½ΠΎΠ΅ мСсто для внСдрСния DI:

@dataclass
class Service:
    client: "Client" = field(default_factory=create_default_client)
default_factory β€” это малСнький Ρ…Π°ΠΊ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ позволяСт ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΊΠΎΠ΄ Ρ‡ΠΈΡ‰Π΅ ΠΈ бСзопаснСС, особСнно ΠΊΠΎΠ³Π΄Π° Ρ€Π°Π±ΠΎΡ‚Π°Π΅ΡˆΡŒ с измСняСмыми структурами ΠΈΠ»ΠΈ слоТной ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ. πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

yield from β€” элСгантная ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° управлСния Если Π²Ρ‹ ΠΏΠΈΡˆΠ΅Ρ‚Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‚ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ β€” Π·Π°Π±ΡƒΠ΄ΡŒΡ‚Π΅ ΠΏΡ€ΠΎ for x in sub(): yield x. Π•ΡΡ‚ΡŒ способ ΠΏΡ€ΠΎΡ‰Π΅ ΠΈ ΠΌΠΎΡ‰Π½Π΅Π΅. ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ yield from позволяСт ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ элСмСнты ΠΈΠ· ΠΏΠΎΠ΄Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Π° Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ, Π±Π΅Π· лишнСго ΠΊΠΎΠ΄Π°. Но Ρ„ΠΈΡˆΠΊΠ° Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² лаконичности β€” ΠΎΠ½ Ρ‚Π°ΠΊΠΆΠ΅ автоматичСски пробрасываСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния ΠΈΠ· ΠΏΠΎΠ΄Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Π°. Π’ΠΎΡ‚ классика:

def gen():
    for x in range(3):
        yield x

def wrapper():
    for x in gen():
        yield x
МоТно ΠΊΠΎΡ€ΠΎΡ‡Π΅ ΠΈ Π»ΡƒΡ‡ΡˆΠ΅:

def wrapper():
    yield from gen()
Но Π³Π»Π°Π²Π½ΠΎΠ΅ β€” yield from пробрасываСт return-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈΠ· ΠΏΠΎΠ΄Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Π° (начиная с Python 3.3):

def sub():
    yield 1
    yield 2
    return 'done'

def main():
    result = yield from sub()
    print('Sub returned:', result)

for _ in main():
    pass
# Π’Ρ‹Π²Π΅Π΄Π΅Ρ‚: Sub returned: done
А Π΅Ρ‰Ρ‘ Ρ‡Π΅Ρ€Π΅Π· yield from ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΠΊΡΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ значСния Π²Π½ΡƒΡ‚Ρ€ΡŒ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Π° β€” Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² сопрограммах:

def delegator():
    result = yield from coroutine()
    print('coroutine done:', result)

def coroutine():
    x = yield
    y = yield
    return x + y

g = delegator()
next(g)          # Π‘Ρ‚Π°Ρ€Ρ‚
next(g)          # coroutine ΠΆΠ΄Π΅Ρ‚ x
g.send(10)       # x = 10
print(g.send(20))  # y = 20 β†’ return 30
# Π’Ρ‹Π²Π΅Π΄Π΅Ρ‚: coroutine done: 30
Π˜Ρ‚ΠΎΠ³: Ссли Π²Ρ‹ ΠΏΠΈΡˆΠ΅Ρ‚Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ β€” освоСниС yield from даст Π²Π°ΠΌ Π»Π°ΠΊΠΎΠ½ΠΈΡ‡Π½Ρ‹ΠΉ синтаксис, проброс return-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ, ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ ΠΈ взаимодСйствиС Π½Π° Π½ΠΎΠ²ΠΎΠΌ ΡƒΡ€ΠΎΠ²Π½Π΅. πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

πŸš€ ΠŸΠΎΠ΄Π±ΠΎΡ€ΠΊΠ° ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Ρ… IT ΠΊΠ°Π½Π°Π»ΠΎΠ² Π² Max БистСмноС администрированиС, DevOps πŸ“Œ https://max.ru/i_odmin ВсС для систСмного администратора https://max.ru/bash_srv Bash Π‘ΠΎΠ²Π΅Ρ‚Ρ‹ https://max.ru/sysadminof Книги для Π°Π΄ΠΌΠΈΠ½ΠΎΠ², ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Π΅ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹ https://max.ru/i_odmin_book Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° БистСмного Администратора https://max.ru/i_devops DevOps: ПишСм ΠΎ Docker, Kubernetes ΠΈ Π΄Ρ€. 1C Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° πŸ“Œ https://max.ru/odin1c_rus CΡ‚Π°Ρ‚ΡŒΠΈ, курсы, совСты, ΡˆΠ°Π±Π»ΠΎΠ½Ρ‹ ΠΊΠΎΠ΄Π° 1Π‘ ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ C++πŸ“Œ https://max.ru/cpp_lib Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° C/C++ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Python πŸ“Œ https://max.ru/python_of Python акадСмия. https://max.ru/BookPython Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Python Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° Java Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° πŸ“Œ https://max.ru/bookjava Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Java Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° GitHub БообщСство πŸ“Œ https://max.ru/githublib Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½ΠΎΠ΅ ΠΈΠ· GitHub Π‘Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… (Data Base) πŸ“Œ https://max.ru/database_info ВсС ΠΏΡ€ΠΎ Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Π€Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° πŸ“Œ https://max.ru/frontend_1 ΠŸΠΎΠ΄Π±ΠΎΡ€ΠΊΠΈ для frontend Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ πŸ“Œ https://max.ru/programmist_of Книги ΠΏΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ https://max.ru/proglb Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста https://max.ru/bfbook Книги для программистов ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ πŸ“Œ https://max.ru/bookflow Π›Π΅ΠΊΡ†ΠΈΠΈ, Π²ΠΈΠ΄Π΅ΠΎΡƒΡ€ΠΎΠΊΠΈ, Π΄ΠΎΠΊΠ»Π°Π΄Ρ‹ с IT ΠΊΠΎΠ½Ρ„Π΅Ρ€Π΅Π½Ρ†ΠΈΠΉ https://max.ru/itmozg ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡΡ‚Ρ‹, Π΄ΠΈΠ·Π°ΠΉΠ½Π΅Ρ€Ρ‹, новости ΠΈΠ· ΠΌΠΈΡ€Π° IT https://max.ru/php_lib Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° PHP программиста πŸ‘¨πŸΌβ€πŸ’»πŸ‘©β€πŸ’» Π¨ΡƒΡ‚ΠΊΠΈ программистов πŸ“Œ https://max.ru/itumor Π¨ΡƒΡ‚ΠΊΠΈ программистов Π—Π°Ρ‰ΠΈΡ‚Π°, Π²Π·Π»ΠΎΠΌ, Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ πŸ“Œ https://max.ru/thehaking Канал ΠΎ кибСрбСзопасности https://max.ru/xakkep_1 Π₯Π°ΠΊΠ΅Ρ€ Free Книги, ΡΡ‚Π°Ρ‚ΡŒΠΈ для Π΄ΠΈΠ·Π°ΠΉΠ½Π΅Ρ€ΠΎΠ² πŸ“Œ https://max.ru/odesigners Π‘Ρ‚Π°Ρ‚ΡŒΠΈ, ΠΊΠ½ΠΈΠ³ΠΈ для Π΄ΠΈΠ·Π°ΠΉΠ½Π΅Ρ€ΠΎΠ² ΠœΠ°Ρ‚Π΅ΠΌΠ°Ρ‚ΠΈΠΊΠ° πŸ“Œ https://max.ru/Pomatematike Канал ΠΏΠΎ ΠΌΠ°Ρ‚Π΅ΠΌΠ°Ρ‚ΠΈΠΊΠ΅ https://max.ru/phismat_1 ΠžΠ±ΡƒΡ‡Π°ΡŽΡ‰ΠΈΠ΅ Π²ΠΈΠ΄Π΅ΠΎ, ΠΊΠ½ΠΈΠ³ΠΈ ΠΏΠΎ Π€ΠΈΠ·ΠΈΠΊΠ΅ ΠΈ ΠœΠ°Ρ‚Π΅ΠΌΠ°Ρ‚ΠΈΠΊΠ΅ Вакансии πŸ“Œ https://max.ru/progjob Вакансии Π² IT ΠœΠΈΡ€ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ πŸ“Œ https://max.ru/mir_teh Канал для Π»ΡŽΠ±ΠΎΠ·Π½Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… Бонус πŸ“Œ https://max.ru/piterspb_78 Π‘Π²Π΅ΠΆΠΈΠ΅ новости Π‘Π°Π½ΠΊΡ‚-ΠŸΠ΅Ρ‚Π΅Ρ€Π±ΡƒΡ€Π³Π° https://max.ru/mockva_life Π‘Π²Π΅ΠΆΠΈΠ΅ новости ΠœΠΎΡΠΊΠ²Ρ‹

Python прСдоставляСт ΠΌΠΎΡ‰Π½ΡƒΡŽ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π΄Π°Ρ‚ΠΎΠΉ ΠΈ Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ β€” datetime. Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚: ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ datetime ΠΈΠΌΠ΅ΡŽΡ‚ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΉ интСрфСйс для ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ часовых поясов (Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ tzinfo), ΠΎΠ΄Π½Π°ΠΊΠΎ сама Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° `datetime Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ Π΅Π³ΠΎ лишь частично, оставляя ΠΎΡΡ‚Π°Π»ΡŒΠ½ΡƒΡŽ Ρ€Π°Π±ΠΎΡ‚Ρƒ сторонним модулям. Π‘Π°ΠΌΡ‹ΠΌ популярным ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΌ для этой Π·Π°Π΄Π°Ρ‡ΠΈ являСтся pytz. Π₯ΠΈΡ‚Ρ€ΠΎΡΡ‚ΡŒ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ pytz Π½Π΅ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ соотвСтствуСт интСрфСйсу tzinfo. Π’ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ pytz прямо ΡƒΠΊΠ°Π·Π°Π½ΠΎ с самого Π½Π°Ρ‡Π°Π»Π°: Β«Π­Ρ‚Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° отличаСтся ΠΎΡ‚ Π·Π°Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ API Python для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΉ tzinfoΒ». Π’Ρ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ просто ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ Π·ΠΎΠ½Ρ‹ pytz Π² Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ tzinfo. Если ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅Ρ‚Π΅, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½ΠΎ Π±Π΅Π·ΡƒΠΌΠ½Ρ‹ΠΌ:

In : paris = pytz.timezone('Europe/Paris')
In : str(datetime(2017, 1, 1, tzinfo=paris))
Out: '2017-01-01 00:00:00+00:09'
ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Π½Π° этот смСщСниС +00:09. ΠŸΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅ использованиС pytz выглядит Ρ‚Π°ΠΊ:

In : str(paris.localize(datetime(2017, 1, 1)))
Out: '2017-01-01 00:00:00+01:00'
ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, послС Π»ΡŽΠ±Ρ‹Ρ… ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ с Π΄Π°Ρ‚ΠΎΠΉ ΠΈ Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ, Π½ΡƒΠΆΠ½ΠΎ Π½ΠΎΡ€ΠΌΠ°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ datetime, Ссли Π΅ΡΡ‚ΡŒ Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒ смСны смСщСния (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π½Π° Π³Ρ€Π°Π½ΠΈΡ†Π΅ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π° Π½Π° Π»Π΅Ρ‚Π½Π΅Π΅ врСмя):

In : new_time = time + timedelta(days=2)
In : str(new_time)
Out: '2018-03-27 00:00:00+01:00'
In : str(paris.normalize(new_time))
Out: '2018-03-27 01:00:00+02:00'
Начиная с Python 3.6, рСкомСндуСтся ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ dateutil.tz вмСсто pytz. Он ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ совмСстим с tzinfo, ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ, Π½Π΅ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ normalize, хотя ΠΈ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΌΠ΅Π΄Π»Π΅Π½Π½Π΅Π΅. Если Π²Π°ΠΌ интСрСсно, ΠΏΠΎΡ‡Π΅ΠΌΡƒ pytz Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ API datetime, ΠΈΠ»ΠΈ Π²Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ большС ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ², ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΠΎΡ‡ΠΈΡ‚Π°ΠΉΡ‚Π΅ Ρ…ΠΎΡ€ΠΎΡˆΡƒΡŽ ΡΡ‚Π°Ρ‚ΡŒΡŽ Π½Π° эту Ρ‚Π΅ΠΌΡƒ. πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

Когда Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ multiprocessing, ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΈΠ· процСссов происходит ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, ΠΎΠ½ΠΎ пСрСдаётся Π² ΠΎΡΠ½ΠΎΠ²Π½ΡƒΡŽ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° сСриализации (pickling). Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ сСриализуСтся, пСрСдаётся Π² Π΄Ρ€ΡƒΠ³ΠΎΠΉ процСсс ΠΈ Ρ‚Π°ΠΌ дСсСриализуСтся ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ. Однако сСриализация ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ нСпростой Π·Π°Π΄Π°Ρ‡Π΅ΠΉ. Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ создаётся с Π»ΡŽΠ±Ρ‹ΠΌ количСством Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ΡΡ Π² Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π΅ args. Π­Ρ‚ΠΈ ΠΆΠ΅ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ ΠΏΡ€ΠΈ дСсСриализации для воссоздания ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ. Но это ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π΅ ΡΡ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Ρ‚Π°ΠΊ, ΠΊΠ°ΠΊ Π²Ρ‹ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚Π΅, особСнно Ссли ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ наслСдованиС. ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

import pickle

class TooMuchWeightError(Exception):
    def __init__(self, weight):
        super().__init__()
        self._weight = weight

pickled = pickle.dumps(TooMuchWeightError(42))
pickle.loads(pickled)
Π’Ρ‹Π·ΠΎΠ² TooMuchWeightError.__init__ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ Π²Ρ‹Π·ΠΎΠ²Ρƒ Exception.__init__, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ устанавливаСт args ΠΊΠ°ΠΊ пустой ΠΊΠΎΡ€Ρ‚Π΅ΠΆ. Π­Ρ‚ΠΎΡ‚ пустой ΠΊΠΎΡ€Ρ‚Π΅ΠΆ Π·Π°Ρ‚Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π² качСствС Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ² ΠΏΡ€ΠΈ дСсСриализации, Ρ‡Ρ‚ΠΎ, ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎ, ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ ошибкС:
TypeError: __init__() missing 1 required positional argument: 'weight'
ΠžΠ±Ρ…ΠΎΠ΄Π½ΠΎΠ΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ β€” Π»ΠΈΠ±ΠΎ Π²ΠΎΠΎΠ±Ρ‰Π΅ Π½Π΅ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ super().__init__() (Ρ‡Ρ‚ΠΎ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ считаСтся ΠΏΠ»ΠΎΡ…ΠΎΠΉ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΎΠΉ ΠΏΡ€ΠΈ наслСдовании), Π»ΠΈΠ±ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ всС Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ явно Π² конструктор Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ класса:

class TooMuchWeightError(Exception):
    def __init__(self, weight):
        super().__init__(weight)
        self._weight = weight
πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

Ѐункция map Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ Π΄Ρ€ΡƒΠ³ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ элСмСнта ΠΈΡ‚Π΅Ρ€ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Π­Ρ‚ΠΎ Π·Π½Π°Ρ‡ΠΈΡ‚, Ρ‡Ρ‚ΠΎ функция Π΄ΠΎΠ»ΠΆΠ½Π° ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ ΠΎΠ΄Π½ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² качСствС Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°:

In : list(map(lambda x: x ** 2, [1, 2, 3]))
Out: [1, 4, 9]
Однако Ссли ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт ΠΈΡ‚Π΅Ρ€ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° β€” это ΠΊΠΎΡ€Ρ‚Π΅ΠΆ, Π±Ρ‹Π»ΠΎ Π±Ρ‹ ΡƒΠ΄ΠΎΠ±Π½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт ΠΊΠΎΡ€Ρ‚Π΅ΠΆΠ° ΠΊΠ°ΠΊ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚. Π’ Python 2 это Π±Ρ‹Π»ΠΎ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ благодаря распаковкС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΊΠΎΡ€Ρ‚Π΅ΠΆΠ° (ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° скобки):

>>> map(lambda (a, b): a + b, [(1, 2), (3, 4)])
[3, 7]
Π’ Python 3 эта Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ исчСзла, Π½ΠΎ Π΅ΡΡ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΎΠ΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ β€” itertools.starmap. Она распаковываСт ΠΊΠΎΡ€Ρ‚Π΅ΠΆΠΈ Π·Π° вас, Π±ΡƒΠ΄Ρ‚ΠΎ функция вызываСтся со Π·Π²Ρ‘Π·Π΄ΠΎΡ‡ΠΊΠΎΠΉ: f(*arg) (ΠΎΡ‚ΡΡŽΠ΄Π° ΠΈ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ):

from itertools import starmap

In [3]: list(starmap(lambda a, b: a + b, [(1, 2), (3, 4)]))
Out[3]: [3, 7]
πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

Ѐункция super() позволяСт ΠΎΠ±Ρ€Π°Ρ‰Π°Ρ‚ΡŒΡΡ ΠΊ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠΌΡƒ (Π±Π°Π·ΠΎΠ²ΠΎΠΌΡƒ) классу. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΡ‡Π΅Π½ΡŒ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ Π² случаях, ΠΊΠΎΠ³Π΄Π° ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½Ρ‹ΠΉ класс Ρ…ΠΎΡ‡Π΅Ρ‚ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ ΠΊ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°, Π° Π½Π΅ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ Π΅Π³ΠΎ:

class BaseTestCase(TestCase):
    def setUp(self):
        self._db = create_db()

class UserTestCase(BaseTestCase):
    def setUp(self):
        super().setUp()
        self._user = create_user()
Имя Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ super Π½Π΅ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ "ΠΎΡ‚Π»ΠΈΡ‡Π½Ρ‹ΠΉ" ΠΈΠ»ΠΈ "ΠΎΡ‡Π΅Π½ΡŒ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΉ". Π’ Π΄Π°Π½Π½ΠΎΠΌ контСкстС слово super ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ "Π²Ρ‹ΡˆΠ΅" (ΠΊΠ°ΠΊ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² словС superintendent β€” Π·Π°Π²Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ). НСсмотря Π½Π° это, super() Π½Π΅ всСгда ссылаСтся Π½Π° Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ класс β€” ΠΎΠ½ ΠΌΠΎΠΆΠ΅Ρ‚ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΈ "сосСдний" класс. Π‘ΠΎΠ»Π΅Π΅ Ρ‚ΠΎΡ‡Π½Ρ‹ΠΌ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ Π±Ρ‹Π»Π° Π±Ρ‹, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, функция next(), Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ возвращаСтся ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ класс согласно Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² (MRO β€” Method Resolution Order). ΠŸΡ€ΠΈΠΌΠ΅Ρ€:

class Top:
    def foo(self):
        return 'top'

class Left(Top):
    def foo(self):
        return super().foo()

class Right(Top):
    def foo(self):
        return 'right'

class Bottom(Left, Right):
    pass

# Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ 'right'
print(Bottom().foo())
ΠžΠ±Ρ€Π°Ρ‚ΠΈ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅: Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρ‹ super() ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΡ‚Π»ΠΈΡ‡Π°Ρ‚ΡŒΡΡ Π² зависимости ΠΎΡ‚ MRO Π²Ρ‹Π·Π²Π°Π²ΡˆΠ΅Π³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°.

>>> Bottom().foo()
'right'
>>> Left().foo()
'top'
πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

Π‘Ρ‚Π°Π½Π΄Π°Ρ€Ρ‚Π½Ρ‹ΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ ΠΏΡƒΡ‚Π΅ΠΉ Π² ΠΎΠ±ΠΎΠ»ΠΎΡ‡ΠΊΠ΅ называСтся globbing. Π¨Π°Π±Π»ΠΎΠ½Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ для сопоставлСния ΠΏΡƒΡ‚Π΅ΠΉ
Π‘Ρ‚Π°Π½Π΄Π°Ρ€Ρ‚Π½Ρ‹ΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ ΠΏΡƒΡ‚Π΅ΠΉ Π² ΠΎΠ±ΠΎΠ»ΠΎΡ‡ΠΊΠ΅ называСтся globbing. Π¨Π°Π±Π»ΠΎΠ½Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ для сопоставлСния ΠΏΡƒΡ‚Π΅ΠΉ, Π½Π°Π·Ρ‹Π²Π°ΡŽΡ‚ΡΡ globs.

$ echo /li*
/lib /lib64
Python ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ globbing с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ модуля glob. Однако Π΅ΡΡ‚ΡŒ Π²Π°ΠΆΠ½ΠΎΠ΅ Π·Π°ΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅: ΠΎΠ±ΠΎΠ»ΠΎΡ‡ΠΊΠ° Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ сам шаблон, Ссли Ρ„Π°ΠΉΠ»Ρ‹ Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½Ρ‹, Π° Python β€” Π½Π΅Ρ‚:

$ echo /zz**
/zz**
$ python -c 'from glob import glob; print(glob("/zz**"))'
[]
πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

ΠžΠ±Ρ‹Ρ‡Π½ΠΎ Π²Ρ‹ взаимодСйствуСтС с Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠΌ, Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Ρ Π΄Π°Π½Π½Ρ‹Π΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ next(gen). Π’ Python 3 Π²Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ значСния ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ Π² Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ g.send(x). Но сущСствуСт Ρ‚Π΅Ρ…Π½ΠΈΠΊΠ°, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π²Ρ‹, вСроятно, Π½Π΅ ΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ΡΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ дСнь, Π° Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, ΠΈ вовсС Π½Π΅ Π·Π½Π°Π΅Ρ‚Π΅: выбрасываниС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ Π²Π½ΡƒΡ‚Ρ€ΠΈ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Π°. Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ gen.throw(e) ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹Π±Ρ€ΠΎΡΠΈΡ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π² Ρ‚ΠΎΠΉ Ρ‚ΠΎΡ‡ΠΊΠ΅, Π³Π΄Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ gen приостановлСн β€” Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Π½Π° инструкции yield. Если Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ это ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, gen.throw(e) Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ Ρ‡Π΅Ρ€Π΅Π· yield (ΠΈΠ»ΠΈ выбрасываСт StopIteration, Ссли Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Π·Π°Π²Π΅Ρ€ΡˆΡ‘Π½). Если Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Π½Π΅ ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, ΠΎΠ½ΠΎ пробрасываСтся ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ ΠΊ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΌΡƒ ΠΊΠΎΠ΄Ρƒ.

def gen():
    try:
        yield 1
    except ValueError:
        yield 2

g = gen()

next(g)
# Out: 1

g.throw(ValueError)
# Out: 2

g.throw(RuntimeError('TEST'))
# RuntimeError: TEST
Π­Ρ‚Π° Ρ‚Π΅Ρ…Π½ΠΈΠΊΠ° позволяСт Π±ΠΎΠ»Π΅Π΅ Ρ‚ΠΎΡ‡Π½ΠΎ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ΠΌ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Π° β€” Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ Π²Π½ΡƒΡ‚Ρ€ΡŒ, Π½ΠΎ ΠΈ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΡΠΎΠΎΠ±Ρ‰Π°Ρ‚ΡŒ ΠΎ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°Ρ… со значСниями, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹ΠΌΠΈ Ρ‡Π΅Ρ€Π΅Π· yield. Однако Ρ‚Π°ΠΊΠΈΠ΅ случаи Π±Ρ‹Π²Π°ΡŽΡ‚ Ρ€Π΅Π΄ΠΊΠΎ, ΠΈ Π²ΡΡ‚Ρ€Π΅Ρ‚ΠΈΡ‚ΡŒ g.throw Π² Π΄ΠΈΠΊΠΎΠΉ ΠΏΡ€ΠΈΡ€ΠΎΠ΄Π΅ ΠΏΠΎΡ‡Ρ‚ΠΈ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ. Π’Π΅ΠΌ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅, Π΄Π΅ΠΊΠΎΡ€Π°Ρ‚ΠΎΡ€ @contextmanager ΠΈΠ· модуля contextlib ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΈΠΌΠ΅Π½Π½ΠΎ Ρ‚Π°ΠΊΡƒΡŽ Ρ‚Π΅Ρ…Π½ΠΈΠΊΡƒ, позволяя ΠΊΠΎΠ΄Ρƒ Π²Π½ΡƒΡ‚Ρ€ΠΈ контСкста ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ.

from contextlib import contextmanager

@contextmanager
def atomic():
    print('BEGIN')

    try:
        yield
    except Exception:
        print('ROLLBACK')
    else:
        print('COMMIT')

with atomic():
    print('ERROR')
    raise RuntimeError()

BEGIN  
ERROR  
ROLLBACK
πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

Одна ΠΈ Ρ‚Π° ΠΆΠ΅ строка ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ прСдставлСна ΠΏΠΎ-Ρ€Π°Π·Π½ΠΎΠΌΡƒ Π² Unicode, ΠΈ стандарт это ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚. Он опрСдСляСт Π΄Π²Π° Ρ‚ΠΈΠΏΠ° эквивалСнтности: ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ каноничСски эквивалСнтными ΠΈΠ»ΠΈ совмСстимыми. ΠšΠ°Π½ΠΎΠ½ΠΈΡ‡Π΅ΡΠΊΠΈ эквивалСнтныС ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ выглядят ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ, Π½ΠΎ содСрТат Ρ€Π°Π·Π½Ρ‹Π΅ ΠΊΠΎΠ΄ΠΎΠ²Ρ‹Π΅ Ρ‚ΠΎΡ‡ΠΊΠΈ. НапримСр, символ ΓΆ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ прСдставлСн ΠΊΠ°ΠΊ LATIN SMALL LETTER O WITH DIAERESIS (U+00F6) ΠΈΠ»ΠΈ ΠΊΠ°ΠΊ комбинация ΠΈΠ· o ΠΈ диакритичСского Π·Π½Π°ΠΊΠ°: LATIN SMALL LETTER O (U+006F) + COMBINING DIAERESIS (U+0308). БовмСстимыС ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ выглядят ΠΏΠΎ-Ρ€Π°Π·Π½ΠΎΠΌΡƒ, Π½ΠΎ ΠΌΠΎΠ³ΡƒΡ‚ Ρ‚Ρ€Π°ΠΊΡ‚ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ с Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния смысла, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ff ΠΈ ff. Для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΈΠ· этих Ρ‚ΠΈΠΏΠΎΠ² эквивалСнтности ΠΌΠΎΠΆΠ½ΠΎ Π½ΠΎΡ€ΠΌΠ°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ строку Π² Unicode, сТимая ΠΈΠ»ΠΈ Ρ€Π°ΡΡˆΠΈΡ€ΡΡ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ. Π’ Python для этого ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ unicodedata:

import unicodedata

modes = [
    # Π‘ΠΆΠ°Ρ‚ΡŒ каноничСски эквивалСнтныС
    'NFC',
    # Π Π°ΡΡˆΠΈΡ€ΠΈΡ‚ΡŒ каноничСски эквивалСнтныС
    'NFD',
    # Π‘ΠΆΠ°Ρ‚ΡŒ совмСстимыС
    'NFKC',
    # Π Π°ΡΡˆΠΈΡ€ΠΈΡ‚ΡŒ совмСстимыС
    'NFKD',
]

s = 'ff + ΓΆ'

for mode in modes:
    norm = unicodedata.normalize(mode, s)
    print('\t'.join([
        mode,
        norm,
        str(len(norm.encode('utf8'))),
    ]))
Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚:
NFC     ff + ΓΆ   8
NFD     ff + ΓΆ   9
NFKC    ff + ΓΆ  7
NFKD    ff + ΓΆ  8
πŸ“² ΠœΡ‹ Π² MAX πŸ‘‰@BookPython

Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Python Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° | Книги ΠΏΠΎ ΠΏΠΈΡ‚ΠΎΠ½Ρƒ - Statistics & analytics of Telegram channel @bookpython