Библиотека Python разработчика | Книги по питону
Погружение в CPython и архитектуру. Разбираем неочевидное поведение (GIL, Memory), Best Practices (SOLID, DDD) и тонкости Django/FastAPI. Решаем задачи с подвохом и оптимизируем алгоритмы. 🐍 По всем вопросам @evgenycarter РКН clck.ru/3Ko7Hq
Mostrar más📈 Análisis del canal de Telegram Библиотека Python разработчика | Книги по питону
El canal Библиотека Python разработчика | Книги по питону (@bookpython) en el segmento lingüístico de Ruso es un actor destacado. Actualmente la comunidad reúne a 18 328 suscriptores, ocupando la posición 7 307 en la categoría Tecnologías y Aplicaciones y el puesto 36 869 en la región Rusia.
📊 Métricas de audiencia y dinámica
Desde su creación el невідомо, el proyecto ha mostrado un crecimiento acelerado, reuniendo a 18 328 suscriptores.
Según los últimos datos del 04 junio, 2026, el canal mantiene una actividad estable. En los últimos 30 días la variación de miembros fue de -86, y en las últimas 24 horas de -1, conservando un alto alcance.
- Estado de verificación: No verificado
- Tasa de interacción (ER): El promedio de interacción de la audiencia es 6.07%. Durante las primeras 24 horas tras publicar, el contenido suele obtener 2.61% de reacciones respecto al total de suscriptores.
- Alcance de las publicaciones: Cada publicación recibe en promedio 1 112 visualizaciones. En el primer día suele acumular 479 visualizaciones.
- Reacciones e interacción: La audiencia responde de forma activa: el promedio de reacciones por publicación es 2.
- Intereses temáticos: El contenido se centra en temas clave como numbers, yield, модуль, none, декоратор.
📝 Descripción y política de contenido
El autor describe el recurso como un espacio para expresar opiniones subjetivas:
“Погружение в CPython и архитектуру. Разбираем неочевидное поведение (GIL, Memory), Best Practices (SOLID, DDD) и тонкости Django/FastAPI. Решаем задачи с подвохом и оптимизируем алгоритмы. 🐍
По всем вопросам @evgenycarter
РКН clck.ru/3Ko7Hq”
Gracias a la alta frecuencia de actualizaciones (últimos datos recibidos el 05 junio, 2026), el canal mantiene la vigencia y un amplio alcance. La analítica demuestra que la audiencia interactúa activamente con el contenido, lo que lo convierte en un punto de referencia dentro de la categoría Tecnologías y Aplicaciones.
try:
cache
except NameError:
cache = {}
На первый взгляд, нет смысла писать что-то подобное. Переменная cache однозначно вызовет NameError в начале выполнения модуля, так как она ещё не была определена.
Однако ситуация меняется, если модуль перезагружается. В этом случае словарь, содержащий все атрибуты модуля, переиспользуется, что даёт возможность модулю сохранить значения из предыдущей версии.
Если модуль изначально спроектирован с учётом перезагрузки, он может использовать эту особенность. Например, приведённый выше код позволяет сохранить кэш между перезагрузками модуля.
👉@BookPythonmath.nan.
NaN не равен ничему, включая самого себя:
>>> math.nan == math.nan
False
Кроме того, объект NaN не является уникальным — можно получить несколько разных объектов NaN из разных источников:
>>> float('nan')
nan
>>> float('nan') is float('nan')
False
Это означает, что обычно нельзя использовать NaN в качестве ключа словаря:
>>> d = {}
>>> d[float('nan')] = 1
>>> d[float('nan')] = 2
>>> d
{nan: 1, nan: 2}
👉@BookPythonNone равен None, поэтому может показаться, что проверку на None можно делать через ==:
ES_TAILS = ('s', 'x', 'z', 'ch', 'sh')
def make_plural(word, exceptions=None):
if exceptions == None: # ← ← ←
exceptions = {}
if word in exceptions:
return exceptions[word]
elif any(word.endswith(t) for t in ES_TAILS):
return word + 'es'
elif word.endswith('y'):
return word[0:-1] + 'ies'
else:
return word + 's'
exceptions = dict(
mouse='mice',
)
print(make_plural('python'))
print(make_plural('bash'))
print(make_plural('ruby'))
print(make_plural('mouse', exceptions=exceptions))
Однако так делать неправильно. Действительно, None равен None, но не только он может быть равен None. Пользовательские объекты тоже могут вернуть True при сравнении с None через ==:
class A:
def __eq__(self, other):
return True
print(A() == None) # True
print(A() is None) # False
Правильный способ проверки на None — использовать is None.
👉@BookPython+:
>>> [1, 2] + [2, 3]
[1, 2, 2, 3]
Кортежи и строки также используют +:
>>> (1, 2) + (2, 3)
(1, 2, 2, 3)
>>> "12" + "23"
'1223'
Deque (двусторонняя очередь) тоже поддерживает +:
>>> deque([1, 2]) + deque([2, 3])
deque([1, 2, 2, 3])
Множества объединяются с помощью оператора |:
>>> {1, 2} | {2, 3}
{1, 2, 3}
Словари объединяются по-другому, и порядок важен, если ключи пересекаются:
>>> {**dict(a=1, b=2), **dict(b=3, c=4)}
{'a': 1, 'b': 3, 'c': 4}
>>> {**dict(b=3, c=4), **dict(a=1, b=2)}
{'b': 2, 'c': 4, 'a': 1}
Counter (счётчик) можно сложить с помощью +, при этом значения суммируются:
>>> Counter(dict(a=1, b=2)) + Counter(dict(b=3, c=4))
Counter({'b': 5, 'c': 4, 'a': 1})
👉@BookPythonEllipsis, которую также можно записать как .... Эта константа не имеет особого значения для интерпретатора, но используется в тех местах, где подобный синтаксис уместен.
numpy поддерживает Ellipsis как аргумент для __getitem__. Например, x[...] возвращает все элементы массива x.
PEP 484 задаёт дополнительный смысл: Callable[..., type] — способ определить тип вызываемых объектов без указания типов аргументов.
Наконец, ... можно использовать, чтобы показать, что функция ещё не реализована. Это полностью корректный Python-код:
def x():
...
👉@BookPython
>>> class A:
... x = 2
... def f():
... print(x)
... f()
...
[...]
NameError: name 'x' is not defined
Обычно это не проблема: методы объявляются внутри класса только для того, чтобы стать методами и вызываться позже:
>>> class A:
... x = 2
... def f(self):
... print(self.x)
...
>>> A().f()
2
Что немного неожиданно — то же самое верно и для генераторов и списковых включений (comprehensions).
Они имеют свою собственную область видимости и не могут обращаться к области видимости класса.
Это особенно логично для генераторов, так как они выполняются уже после того, как создание класса завершено.
>>> class A:
... x = 2
... y = [x for _ in range(5)]
...
[...]
NameError: name 'x' is not defined
Comprehensions при этом не имеют доступа к self.
Единственный способ заставить это работать - добавить ещё один уровень области видимости, например, через lambda (да, это выглядит не слишком красиво):
>>> class A:
... x = 2
... y = (lambda x=x: [x for _ in range(5)])()
...
>>> A.y
[2, 2, 2, 2, 2]
👉@BookPythondict, хотя выглядят они абсолютно одинаково:
>>> from sys import getsizeof
>>> class A:
... pass
...
>>> a = dict()
>>> b = A().__dict__
>>> type(a)
<class 'dict'>
>>> type(b)
<class 'dict'>
>>> a
{}
>>> b
{}
>>> getsizeof(a)
240
>>> getsizeof(b)
112
Чтобы уменьшить потребление памяти, словари для __dict__ реализованы иначе. Они разделяют ключи между всеми экземплярами класса A. Однако важно понимать, что b на самом деле не меньше, чем a, - это просто особенность работы getsizeof.
👉@BookPythonrepr для других объектов внутри собственного метода __repr__ заключается в том, что нельзя гарантировать, что ни один из этих объектов не равен self, и вызов не окажется рекурсивным:
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, ...)
👉@BookPythontime.monotonic() никогда не идёт назад, даже если системные часы были изменены:
from contextlib import contextmanager
import time
@contextmanager
def timeit():
start = time.monotonic()
yield
print(time.monotonic() - start)
def main():
with timeit():
time.sleep(2)
main()
👉@BookPython@property:
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
Ниже приведён пример того, как можно определить функцию, которая использует дополнительные функции для особых случаев:
from functools import wraps
def make_case_decorator(func):
def case_decorator(*case_decorator_args):
def decorator(special_case_func):
@wraps(func)
def decorated(*args):
if case_decorator_args == args:
return special_case_func(*args)
return func(*args)
decorated.case = make_case_decorator(decorated)
return decorated
return decorator
return case_decorator
def special_cases(func):
@wraps(func)
def decorated(*args):
return func(*args)
decorated.case = make_case_decorator(decorated)
return decorated
@special_cases
def fact(x):
return x * fact(x - 1)
@fact.case(0)
def fact(x):
return 1
@fact.case(10)
def fact(x):
print(f'(сработала оптимизация для {x})')
return 3628800
👉@BookPython2:
def make_closure(x):
def closure():
print(x)
return closure
make_closure(2)()
Вызывает UnboundLocalError: local variable 'x' referenced before assignment:
def make_closure(x):
def closure():
print(x)
x *= 2
print(x)
return closure
make_closure(2)()
Чтобы это заработало, нужно использовать nonlocal.
Оно явно сообщает интерпретатору, что присваивание не создает новую локальную переменную, а работает с переменной из замыкания:
def make_closure(x):
def closure():
nonlocal x
print(x)
x *= 2
print(x)
return closure
make_closure(2)()
👉@BookPython
¡Ya disponible! Investigación de Telegram 2025 — los principales insights del año 
