Библиотека Python разработчика | Книги по питону
Погружение в 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 312 subscribers, ranking 7 334 in the Technologies & Applications category and 36 889 in the Russia region.
📊 Audience metrics and dynamics
Since its creation on невідомо, the project has demonstrated rapid growth, gathering an audience of 18 312 subscribers.
According to the latest data from 12 June, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by -83 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.76% reactions from the total number of subscribers.
- Post reach: On average, each post receives 1 006 views. Within the first day, a publication typically gains 505 views.
- Reactions and interaction: The audience actively supports content: the average number of reactions per post is 2.
- 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 13 June, 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.
obj.x = y you can't be sure that the attributed of obj named x is now equal to y. Python descriptor protocol lets define how attribute assignment is handled.
class Descriptor:
def __set__(self, obj, value):
obj.test = value
class A:
x = Descriptor()
In this example, x is never assigned, but the test attribute is assigned instead:
In : a = A()
In : a.x = 42
In : a.test
Out: 42
In : a.x
Out: <__main__.Descriptor at 0x7ff7baef51d0>
In case you actually need to change the x attribute as a part of tests or advanced metaprogramming, you have to modify __dict__ directly:
In : a.__dict__['x'] = 42
In : a.x
Out: 42Ellipsis which is also can be written as .... This constant has no special meaning for the interpreter but is used in places where such syntax looks appropriate.
numpy support Ellipsis as a __getitem__ argument, e. g. x[...] returns all elements of x.
PEP 484 defines additional meaning: Callable[..., type] is a way to define a type of callables with no argument types specified.
Finally, you can use to indicate that function is not yet implemented. This is a completely valid Python code:
def x():
...asyncio, if coroutine raises an exception, it's then propagated to the code that awaits the corresponding future. If multiple places do await, every one of them gets the exception (since it's stored in the exception). The following code prints error five times:
import asyncio
async def error():
await asyncio.sleep(1)
raise ValueError()
async def waiter(task):
try:
await task
except ValueError:
print('error')
else:
print('OK')
async def main():
task = asyncio.get_event_loop().create_task(error())
for _ in range(5):
asyncio.get_event_loop().create_task(waiter(task))
await asyncio.sleep(2)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
If an exception is raised, but the task is never awaited, the exception is lost. In that case, when the task is destroyed, it warns you with “Task exception was never retrieved” message.
When you use await asyncio.gather(tasks) and one of the tasks raises an exception, it is propagated to you. However, if multiple tasks raise exceptions, you still only get the first one, the others are silently lost:
import asyncio
async def error(i):
await asyncio.sleep(1)
raise ValueError(i)
async def main():
try:
await asyncio.gather(
error(1),
error(2),
error(3),
)
except ValueError as e:
print(e)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
You may use gather with return_exceptions=True that make it return exceptions as though they are regular result values. The following code prints [42, ValueError(2,), ValueError(3,)]:
import asyncio
async def error(i):
await asyncio.sleep(1)
if i > 1:
raise ValueError(i)
return 42
async def main():
results = await asyncio.gather(
error(1),
error(2),
error(3),
return_exceptions=True,
)
print(results)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())>>> print = 42
>>> print(42)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
That may be helpful if your module defines some functions that have the same name as built-in ones. That also happens if you practice metaprogramming and you accept an arbitrary string as an identifier.
However, even if you shadow some built-in names, you still may want to have access to things they initially referred to. The builtins module exists exactly for that:
>>> import builtins
>>> print = 42
>>> builtins.print(1)
1
The __builtins__ variable is also available in most modules. There is a catch though. First, this is a cpython implementation detail and usually should not be used at all. Second, __builtins__ might refer to either builtins or builtins.__dict__, depending on how exactly the current module was loaded.sys.builtin_module_names to get the full list of such modules. The notable examples are sys, gc, time and so on.
Usually you don't care whether the module is built-in or not; however, you should be aware, that import always looks for a module among built-ins first. So, the built-in sys module is loaded even if you have sys.py available. On the other hand, if you have, say, datetime.py in the current directory it indeed can be loaded instead of the standard datetime module.__hash__ method that returns an integer value. To get a hash of the value, the hash built-in function is used.
Built-in types that are not mutable are hashable by default. All custom objects are also hashable, but there is a catch. If you define __eq__ method for your custom type, then you should define such __hash__ that hash(a) == hash(b) for every a and b that are equal. Violating this rule may result in dictionary malfunctioning:
class A:
def __init__(self, x):
self.x = x
def __hash__(self):
return random.randrange(10000)
def __eq__(self, other):
return self.x == other.x
In : d = {}
In : d[A(2)] = 2
In : d.get(A(2), 0)
Out: 0
Mind that though once you define __eq__ in the class, the default __hash__ method is removed since the default implementation is no longer suitable (with it all values are unequal).PEP 8 is a famous style guide for Python code. It's not enforced by the interpreter but you are highly discouraged to ignore it.
There is a tool to automatically check whether your code is following PEP 8 recommendations. Its former name is pep8, but it was renamed to pycodestyle at the request of Guido. Now you should use pycodestyle installed with pip intall pycodestyle only.
You can check whether pycodestyle is happy with your project like this:
$ pycodestyle . -qq --statistics
1 E302 expected 2 blank lines, found 1
1 E305 expected 2 blank lines after class
or function definition, found 1
20 E501 line too long (83 > 79 characters)
Available now! Telegram Research 2025 — the year's key insights 
