Библиотека Python разработчика | Книги по питону
Погружение в CPython и архитектуру. Разбираем неочевидное поведение (GIL, Memory), Best Practices (SOLID, DDD) и тонкости Django/FastAPI. Решаем задачи с подвохом и оптимизируем алгоритмы. 🐍 По всем вопросам @evgenycarter РКН clck.ru/3Ko7Hq
Ko'proq ko'rsatish📈 Telegram kanali Библиотека Python разработчика | Книги по питону analitikasi
Библиотека Python разработчика | Книги по питону (@bookpython) Rus til segmentidagi kanali faol ishtirokchi. Hozirda hamjamiyat 18 123 obunachidan iborat bo'lib, Texnologiyalar & Aralashmalar toifasida 7 044-o'rinni va Rossiya mintaqasida 36 322-o'rinni egallagan.
📊 Auditoriya ko‘rsatkichlari va dinamika
невідомо sanasidan buyon loyiha tez o‘sib, 18 123 obunachiga ega bo‘ldi.
27 Avgust, 2026 dagi oxirgi ma’lumotlarga ko‘ra kanal barqaror faollikka ega. Oxirgi 30 kunda obunachilar soni -72 ga, so‘nggi 24 soatda esa -4 ga o‘zgardi va umumiy qamrov yuqori darajada qolmoqda.
- Tasdiqlash holati: Tasdiqlanmagan
- Jalb etish (ER): Auditoriya o‘rtacha 5.48% darajada jalb etiladi. Nashrdan keyingi dastlabki 24 soatda kontent odatda umumiy obunachilar sonining 2.70% ini tashkil etuvchi reaksiyalarni to‘playdi.
- Post qamrovi: Har bir post o‘rtacha 994 marta ko‘riladi; birinchi sutkada odatda 490 ta ko‘rish yig‘iladi.
- Reaksiyalar va o‘zaro ta’sir: Auditoriya faol: har bir postga o‘rtacha 3 ta reaksiya keladi.
- Tematik yo‘nalishlar: Kontent numbers, yield, модуль, none, декоратор kabi asosiy mavzularga jamlangan.
📝 Tavsif va kontent siyosati
Muallif resursni shaxsiy fikrni ifoda etish maydoni sifatida ta’riflaydi:
“Погружение в CPython и архитектуру. Разбираем неочевидное поведение (GIL, Memory), Best Practices (SOLID, DDD) и тонкости Django/FastAPI. Решаем задачи с подвохом и оптимизируем алгоритмы. 🐍
По всем вопросам @evgenycarter
РКН clck.ru/3Ko7Hq”
Yuqori yangilanish chastotasi (oxirgi ma’lumot 28 Avgust, 2026 da olingan) sababli kanal doimo dolzarb va katta qamrovli bo‘lib qoladi. Analitika auditoriya kontent bilan faol hamkorlik qilishini, uni Texnologiyalar & Aralashmalar toifasidagi muhim ta’sir nuqtasiga aylantirishini ko‘rsatadi.
+= и + являются разными. За их поведение отвечают методы __iadd__ и __add__ соответственно.
class A:
def __init__(self, x):
self.x = x
def __iadd__(self, another):
self.x += another.x
return self
def __add__(self, another):
return type(self)(self.x + another.x)
Если __iadd__ не определён, выражение a += b сводится к простому a = a + b.
Обычно разница между += и + в том, что первый изменяет объект, а второй создаёт новый:
>>> a = [1, 2, 3]
>>> b = a
>>> a += [4]
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3, 4]
>>> a = a + [5]
>>> a
[1, 2, 3, 4, 5]
>>> b
[1, 2, 3, 4]
👉@BookPythonx in g. Python будет итерировать g, пока x не найдётся или генератор не исчерпается.
>>> def g():
... print(1)
... yield 1
... print(2)
... yield 2
... print(3)
... yield 3
...
>>> 2 in g()
1
2
True
Однако range() делает для вас больше. В нём переопределён магический метод __contains__, который позволяет оператору in работать с сложностью O(1):
In [1]: %timeit 10**20 in range(10**30)
375 ns ± 10.7 ns per loop
Учтите, что это не работает для функции xrange() в Python 2.
👉@BookPython__class__:
>>> [1, 2].__class__
<class 'list'>
Однако более привычный способ получить класс — использовать функцию type. Это также единственный способ, который работает для классов старого стиля.
>>> type([1, 2])
<class 'list'>
Кроме того, если вы хотите проверить, является ли некоторый объект экземпляром данного класса, следует использовать isinstance вместо прямого сравнения:
>>> class A:
... pass
...
>>> class B(A):
... pass
...
>>> type(B())
<class '__main__.B'>
>>> isinstance(B(), A)
True
👉@BookPython__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'
👉@BookPython