Библиотека Python разработчика | Книги по питону
Погружение в CPython и архитектуру. Разбираем неочевидное поведение (GIL, Memory), Best Practices (SOLID, DDD) и тонкости Django/FastAPI. Решаем задачи с подвохом и оптимизируем алгоритмы. 🐍 По всем вопросам @evgenycarter РКН clck.ru/3Ko7Hq
Показати більше📈 Аналітичний огляд Telegram-каналу Библиотека Python разработчика | Книги по питону
Канал Библиотека Python разработчика | Книги по питону (@bookpython) у мовному сегменті Російська є активним учасником. На даний момент спільнота об'єднує 17 967 підписників, посідаючи 7 269 місце в категорії Технології та додатки та 36 632 місце у регіоні Росія.
📊 Показники аудиторії та динаміка
З моменту свого створення невідомо, проект продемонстрував стрімке зростання, зібравши аудиторію у 17 967 підписників.
За останніми даними від 29 жовтня, 2026, канал демонструє стабільну активність. Хоча за останні 30 днів спостерігається зміна кількості учасників на -98, а за останні 24 години на -6, загальне охоплення залишається високим.
- Статус верифікації: Не верифікований
- Рівень залученості (ER): Середній показник залученості аудиторії становить 5.47%. Протягом перших 24 годин після публікації контент зазвичай збирає 2.71% реакцій від загальної кількості підписників.
- Охоплення публікацій: В середньому кожен допис отримує 983 переглядів. Протягом першої доби публікація в середньому набирає 487 переглядів.
- Реакції та взаємодія: Аудиторія активно підтримує контент: середня кількість реакцій на один пост – 4.
- Тематичні інтереси: Контент зосереджений навколо ключових тем, таких як numbers, yield, модуль, none, декоратор.
📝 Опис та контентна політика
Автор описує ресурс як майданчик для висловлення суб'єктивної думки:
“Погружение в CPython и архитектуру. Разбираем неочевидное поведение (GIL, Memory), Best Practices (SOLID, DDD) и тонкости Django/FastAPI. Решаем задачи с подвохом и оптимизируем алгоритмы. 🐍
По всем вопросам @evgenycarter
РКН clck.ru/3Ko7Hq”
Завдяки високій частоті оновлень (останні дані отримано 30 жовтня, 2026), канал підтримує актуальність та високий рівень охоплення публікацій. Аналітика показує, що аудиторія активно взаємодіє з контентом, що робить його важливою точкою впливу в категорії Технології та додатки.
__bases__; он возвращает непосредственных родителей класса:
class A:
pass
class B(A):
pass
class C(A):
pass
class D(B, C):
pass
print(D.__bases__)
# (<class '__main__.B'>, <class '__main__.C'>)
Второй —
class B он возвращает кортеж со всеми классами, которые задействованы при разрешении методов (отсюда и название), то есть родителей, их родителей и так далее:
print(D.__mro__)
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
👉@BookPython
(x for x in range(100) if random() > 0.5)
Если вы пишете свой итерируемый объект и хотите добавить такую подсказку, определите метод __length_hint__. Если же длина известна точно, лучше использовать len.
Если вы используете итерируемый объект и хотите узнать его ожидаемую длину, применяйте функцию operator.length_hint.
👉@BookPython
from itertools import tee
def neighbours(iterable, n):
neighbours = tee(iterable, n)
for i, neighbour in enumerate(neighbours):
for _ in range(i):
next(neighbour)
return zip(*neighbours)
fibb = [1, 1, 2, 3, 5, 8, 13, 21]
for a, b, c in neighbours(fibb, 3):
assert c == a + b
В этом примере мы разветвляем исходный итерируемый объект с помощью tee, затем сдвигаем полученные итераторы с помощью next, чтобы второй начинался со второго элемента исходного итерируемого объекта, а третий — с третьего, и затем объединяем их обратно с помощью zip.
👉@BookPython IndexError, и KeyError, вы можете и должны использовать LookupError — их общего предка. Это оказывается полезным при работе со сложными вложенными данными:
try:
db_host = config['databases'][0]['hosts'][0]
except LookupError:
db_host = 'localhost'
👉@BookPython
In : p = Pair(1, 2)
In : p
Out: Pair(1, 2)
In : p.right = p
In : p
Out: [...]
RecursionError: maximum recursion depth exceeded while calling a Python object
Чтобы просто решить эту проблему, можно использовать декоратор reprlib.recursive_repr:
@reprlib.recursive_repr()
def **repr**(self):
class_name = type(self).**name**
return f'{class_name}({self.left!r}, {self.right!r})'
Теперь всё работает:
In : p = Pair(1, 2)
In : p.right = p
In : p
Out: Pair(1, ...)
👉@BookPython
class truncater:
def __init__(self, length):
self._length = length
def __call__(self, s):
return s[0:self._length]
print(truncater(4)('abcdabcd')) # abcd
Поскольку декоратор по сути является функцией высшего порядка, его также можно реализовать в виде вызываемого объекта вместо функции:
class cached:
def __init__(self, func):
self._func = func
self._cache = {}
def __call__(self, arg):
if arg not in self._cache:
self._cache[arg] = self._func(arg)
return self._cache[arg]
@cached
def sqr(x):
return x * x
👉@BookPython
class A: pass
a = A()
a.x = 1
a.__dict__
# {'x': 1}
При прямом доступе к этому словарю можно даже создать атрибуты, которые не являются допустимыми идентификаторами Python (то есть получить их через стандартный синтаксис obj.attr не получится):
a.__dict__[' '] = ' '
getattr(a, ' ')
# ' '
Можно также попросить Python хранить атрибуты непосредственно в памяти (как у простых структур C) с помощью slots. Это экономит память и немного ускоряет доступ к атрибутам, так как не происходит поиска в словаре.
class Point:
__slots__ = ['x', 'y']
Есть несколько моментов, которые нужно помнить при использовании slots. Во-первых, нельзя задавать атрибуты, не указанные в slots. Во-вторых, если класс наследуется от класса с slots, его slots не перекрывают родительские, а добавляются к ним:
class Parent: __slots__ = ['x']
class Child(Parent): __slots__ = ['y']
c = Child()
c.x = 1
c.y = 2
В-третьих, нельзя наследоваться сразу от двух разных классов с непустыми slots, даже если они совпадают.
Помни, что slots предназначены для оптимизации, а не для ограничения набора атрибутов.
👉@BookPythonos.path. Модуль содержит множество функций, которые обрабатывают строки как пути и выполняют полезные операции, такие как объединение путей и прочее:
>>> import os.path
>>> os.path.join('/usr', 'local')
'/usr/local'
>>> os.path.dirname('/var/log')
'/var'
Однако, начиная с Python 3.4, доступен новый модуль pathlib, предлагающий объектно-ориентированный подход:
>>> from pathlib import Path
>>> Path('/usr') / Path('local')
PosixPath('/usr/local')
>>> Path('/usr') / 'local'
PosixPath('/usr/local')
>>> Path('/var/log').parent
PosixPath('/var')
>>> Path('/var/log').parent.name
'var'
👉@BookPythonmatch-case
Теперь можно использовать «захват» значений прямо в паттернах:
def http_status(code):
match code:
case 200 | 201 | 202 as ok:
return f"Success: {ok}"
case 400 as bad | 404 as bad:
return f"Client error: {bad}"
case _:
return "Other"
Большая гибкость и меньше «шаблонных» переменных!
2️⃣ Новый оператор f”{…=}" для отладки
Позволяет вывести и имя, и значение переменной в одной строке:
user = "Alice"
age = 29
print(f"{user=}, {age=}")
# Выведет: user='Alice', age=29
Больше никаких лишних print("user", user)!
3️⃣ Оптимизация работы с памятью и скорость
Команда CPython продолжает ускорение интерпретатора:
* Выделение объектов стало быстрее
* Сборщик мусора реже «паузит» приложение
Это особенно заметно в тяжёлых сервисах и бэкендах.
4️⃣ Новые API для типов
Добавили typing.Self и более гибкие Generic-типизации:
from typing import Self
class Builder:
def set_name(self, name: str) -> Self:
self.name = name
return self
b = Builder().set_name("Demo")
Удобнее писать цепочки вызовов без «# type: ignore»!
💡 Что попробовать прямо сейчас?
1. Установить Python 3.12 pre-release:
pyenv install 3.12.0b4
2. Переписать пару функций с match-case.
3. Пощупать f"{var=}" в дебаге.
👉@BookPython
>>> def enclose(gen, before='{', after='}'):
... yield before
... for x in gen:
... yield x
... yield after
...
>>> list(enclose(range(5)))
['{', 0, 1, 2, 3, 4, '}']
Однако предпочтительнее использовать yield from:
>>> def enclose(gen, before='{', after='}'):
... yield before
... yield from gen
... yield after
yield from не только работает быстрее, но и автоматически обрабатывает передачу значений во вложенные генераторы, возврат значений из генераторов и даже выброс исключений внутри вложенного генератора.
👉@BookPython
def append_length(lst=[]):
lst.append(len(lst))
return lst
print(append_length([1, 2])) # [1, 2, 2]
print(append_length()) # [0]
print(append_length()) # [0, 1]
Однако в некоторых случаях, например при реализации кешей, такое поведение может быть полезным:
def fact(x, cache={0: 1}):
if x not in cache:
cache[x] = x * fact(x - 1)
return cache[x]
print(fact(5))
В этом примере мы сохраняем вычисленные значения факториала внутри значения аргумента по умолчанию. Причём к этому значению даже можно обратиться напрямую:
>>> fact.__defaults__
({0: 1, 1: 1, 2: 2, 3: 6, 4: 24, 5: 120},)
👉@BookPython