ar
Feedback

لا تقع ضحية للمخادعين! تيليمتريو يكتشف ويُميّز هذه القنوات 👉 إذا كنت تريد رؤية العلامة، اشترك

Библиотека Python разработчика | Книги по питону

Библиотека Python разработчика | Книги по питону

الذهاب إلى القناة على Telegram

Погружение в CPython и архитектуру. Разбираем неочевидное поведение (GIL, Memory), Best Practices (SOLID, DDD) и тонкости Django/FastAPI. Решаем задачи с подвохом и оптимизируем алгоритмы. 🐍 По всем вопросам @evgenycarter РКН clck.ru/3Ko7Hq

إظهار المزيد

📈 نظرة تحليلية على قناة تيليجرام Библиотека Python разработчика | Книги по питону

تُعد قناة Библиотека Python разработчика | Книги по питону (@bookpython) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 17 969 مشتركاً، محتلاً المرتبة 7 264 في فئة التكنولوجيات والتطبيقات والمرتبة 36 611 في منطقة روسيا.

📊 مؤشرات الجمهور والحراك

منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 17 969 مشتركاً.

بحسب آخر البيانات بتاريخ 30 أكتوبر, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار -95، وفي آخر 24 ساعة بمقدار -1، مع بقاء الوصول العام مرتفعاً.

  • حالة التحقق: غير موثّقة
  • معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 5.36‎%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً 2.75‎% من ردود الفعل نسبةً إلى إجمالي المشتركين.
  • وصول المنشورات: يحصل كل منشور على متوسط 963 مشاهدة. وخلال اليوم الأول يجمع عادةً 494 مشاهدة.
  • التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 4.
  • الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل numbers, yield, модуль, none, декоратор.

📝 الوصف وسياسة المحتوى

يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
“Погружение в CPython и архитектуру. Разбираем неочевидное поведение (GIL, Memory), Best Practices (SOLID, DDD) и тонкости Django/FastAPI. Решаем задачи с подвохом и оптимизируем алгоритмы. 🐍 По всем вопросам @evgenycarter РКН clck.ru/3Ko7Hq”

بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 31 أكتوبر, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.

17 969
المشتركون
-124 ساعات
-287 أيام
-9530 أيام
أرشيف المشاركات
Конкурс! Начинаем год с подарков от Actibo После праздников не всегда легко вернуться к работе, поэтому предлагаем вам немног
Конкурс! Начинаем год с подарков от Actibo После праздников не всегда легко вернуться к работе, поэтому предлагаем вам немного взбодриться. ✨Разыгрываем три ящика энергетических напитков Actibo, по 12 баночек в каждом. Переходи по ссылке к розыгрышу и выполняй условия. Узнать больше #реклама О рекламодателе

Рассмотрим следующую иерархию классов:

class GrandParent:
    pass

class Parent1(GrandParent):
    pass

class Parent2(GrandParent):
    pass

class Child(Parent1, Parent2):
    pass
В каком порядке будет производиться поиск метода Child.x()? Наивный подход заключается в рекурсивном поиске через все родительские классы, что даст порядок: Child, Parent1, GrandParent, Parent2. Такой метод используется во многих языках программирования, однако он не совсем логичен, так как Parent2 более специфичен, чем GrandParent, и его нужно проверять раньше. Чтобы исправить эту проблему, Python использует линеаризацию C3 (C3 superclass linearization), алгоритм, который всегда ищет метод сначала во всех дочерних классах, а затем уже в родительских. Пример вывода MRO (Method Resolution Order):

In : Child.__mro__
Out:
(__main__.Child,
 __main__.Parent1,
 __main__.Parent2,
 __main__.GrandParent,
 object)
👉@BookPython

Сочи, в продаже студия с ремонтом, ипотека без ПВ! - 9 мин до моря – строительство по ФЗ-214 – вид на горы – пятиэтажный паркинг – благоустроенная территория – школа и детский сад на территории Квартиры от 18м² доступные в: ✅ ипотеку (возможна программа без первоначального взноса ✅ беспроцентную рассрочку ✅ материнский капитал Оставь телефон чтобы узнать цену! Узнать цену Финансовые услуги оказывает: ПАО Банк ВТБ, ПАО "Совкомбанк". #реклама mrqz.me О рекламодателе

Обе конструкции for и with могут быть асинхронными. async with использует магические методы __aenter__ и __aexit__, а async for — методы __aiter__ и __anext__. Все они асинхронные, и внутри них можно использовать await:

import asyncio

class Sleep:
    def __init__(self, t):
        self._t = t

    async def __aenter__(self):
        await asyncio.sleep(self._t / 2)

    async def __aexit__(self, *args):
        await asyncio.sleep(self._t / 2)

async def main():
    async with Sleep(2):
        print('*')

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Когда вы реализуете метод __iter__, часто вместо написания итератора с методом __next__ используется оператор yield, который делает метод __iter__ генератором:

class Bracketed:                  
    def __init__(self, data):     
        self._data = data         
                                  
    def __iter__(self):           
        for x in self._data:      
            yield '({})'.format(x)
                                  
print(list(Bracketed([1, 2, 3]))) 
# ['(1)', '(2)', '(3)']
PEP 525 позволяет делать то же самое с методом __aiter__. Наличие операторов yield и await в теле функции делает её асинхронным генератором. В то время как await используется для взаимодействия с циклом событий, yield управляет работой с for:

import asyncio                          
                                        
class Slow:                             
    def __init__(self, data, t=1):      
        self._data = data               
        self._t = t                     
                                        
    async def __aiter__(self):          
        for x in self._data:            
            await asyncio.sleep(self._t)
            yield x                     
                                        
async def main():                       
    async for x in Slow([1, 2, 3]):     
        print(x)                        
                                        
loop = asyncio.get_event_loop()         
loop.run_until_complete(main())
👉@BookPython

. Пожалуйста,не игнорируйте наше приглашение! Сегодня мы хотим поделиться с вами полезной подборкой каналов которые могут быть вам полезны Скорее выбирайте категорию: Срок действия приглашений всего 1 час! ✅Вяжем шапки,варежки,свитера - t.me/+Hdmk0q50F2pkZTQy ✅АМИГУРУМИ-Вяжем игрушки- t.me/+VmvP1ECGDHxkODA6 ✅ Вязание(видео-уроки)- t.me/+m6L00g4STpszYWJi ✅Вяжем детям- t.me/+ksSjU7lzERw0MzYy ✅Вязание для новичков- t.me/+0sfy52JoKXExODZi Вяжем носочки- t.me/+HFXLXcKLa0cwMWMy Вязание крючком- t.me/+uPHYFp-PVuFkOTIy Вязание спицами- t.me/+9hwOHqLS0VA3ZjRi Узоры крючком- t.me/+DL6dsn4DQGsyNTRi Узоры спицами- t.me/+iwAtESzRlnw2ZjAy Схемы вязания- t.me/+wMa55NfPqWoxOWVi Бесплатные выкройки,уроки шитья - t.me/+NDrsreeCCEIwM2Qy Шитье для новичков- t.me/+472nw5vr3b05ZDgy Узнать больше #реклама О рекламодателе

Если вы хотите передать данные по цепочке вызовов, самый простой способ — использовать аргументы функций. Однако в некоторых случаях модифицировать все функции в цепочке, чтобы передать новые данные, крайне неудобно. Вместо этого вы можете настроить некоторый контекст, который будет доступен для всех функций по цепочке. Как это можно реализовать технически? Самое простое решение — глобальная переменная. В Python также можно использовать модули и классы как хранилища контекста, так как они, строго говоря, тоже являются глобальными переменными. Вы, вероятно, делаете это ежедневно, например, для работы с логгерами. Если ваше приложение многопоточное, обычная глобальная переменная не подойдет, так как она не является потокобезопасной. Одновременно может выполняться несколько цепочек вызовов, и каждая из них нуждается в собственном контексте. Модуль threading решает эту проблему с помощью объекта threading.local(), который является потокобезопасным. Вы можете хранить данные, просто устанавливая атрибуты, например: threading.local().symbol = '@'. Но оба этих подхода не подходят для асинхронных приложений, где функции не только вызываются, но и могут быть приостановлены с помощью await. Если корутина выполняет await, цикл событий может переключиться на другую корутину из совершенно другой цепочки вызовов. Это приведет к некорректной работе, как в следующем примере:

import asyncio
import sys

global_symbol = '.'

async def indication(timeout):
    while True:
        print(global_symbol, end='')
        sys.stdout.flush()
        await asyncio.sleep(timeout)

async def sleep(t, indication_t, symbol='.'):
    loop = asyncio.get_event_loop()

    global global_symbol
    global_symbol = symbol
    loop.create_task(indication(indication_t))
    await asyncio.sleep(t)

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(
    sleep(1, 0.1, '0'),
    sleep(1, 0.1, 'a'),
    sleep(1, 0.1, 'b'),
    sleep(1, 0.1, 'c'),
))
Решить эту проблему можно, если цикл событий будет устанавливать и восстанавливать контекст каждый раз, когда он возобновляет выполнение корутины. Модуль aiotask_context реализует это, изменяя способ создания задач с помощью loop.set_task_factory. Пример рабочей версии:

import asyncio                                
import sys                                    
import aiotask_context as context             
                                              
async def indication(timeout):                
    while True:                               
        print(context.get('symbol'), end='')  
        sys.stdout.flush()                    
        await asyncio.sleep(timeout)          
                                              
async def sleep(t, indication_t, symbol='.'): 
    loop = asyncio.get_event_loop()           
                                              
    context.set(key='symbol', value=symbol)   
    loop.create_task(indication(indication_t))
    await asyncio.sleep(t)                    
                                              
loop = asyncio.get_event_loop()               
loop.set_task_factory(context.task_factory)   
loop.run_until_complete(asyncio.gather(       
    sleep(1, 0.1, '0'),                       
    sleep(1, 0.1, 'a'),                       
    sleep(1, 0.1, 'b'),                       
    sleep(1, 0.1, 'c'),                       
))
👉@BookPython

Когда корутина asyncio хочет остановиться и взаимодействовать с циклом событий (event loop), она использует await obj (или yield from obj до Python 3.6). Объект obj должен быть другой корутиной, объектом asyncio.Future или любым пользовательским объектом, похожим на Future (любой объект, у которого определен метод __await__).

async def coroutine():
    await another_coroutine()

async def another_coroutine():
    future = asyncio.Future()
    await future

loop = asyncio.get_event_loop()
loop.run_until_complete(coroutine())
Когда корутина ожидает (await) другую корутину, вторая начинает выполняться вместо первой. Если она ожидает третью, то выполняется третья. Это продолжается до тех пор, пока какая-нибудь корутина не ожидает объект Future. Объект Future фактически возвращает значение, и тогда цикл событий (event loop) получает управление. Какое значение возвращает Future? Оно возвращает сам себя. Можете ли вы напрямую использовать yield для Future? Нет, это внутренняя деталь, о которой вам обычно не нужно беспокоиться.

class Awaitable:
    def __await__(self):
        future = asyncio.Future()
        yield future
            # RuntimeError: yield was used
            # instead of yield from in task

async def coroutine():
    await Awaitable()

loop = asyncio.get_event_loop()
loop.run_until_complete(coroutine())
Почему возникает эта ошибка? Как asyncio понимает, что это вы используете yield для Future, а не сам Future? Есть простая защита: Future устанавливает внутренний флаг перед тем, как вернуть управление. 👉@BookPython

Ну не умею я красиво одеваться! Давай научу, выбирай свой возраст: Мне 18-25 лет - t.me/+brfkWSTU5XsyZjFi Мне 26-35 лет - t.m
Ну не умею я красиво одеваться! Давай научу, выбирай свой возраст: Мне 18-25 лет - t.me/+brfkWSTU5XsyZjFi Мне 26-35 лет - t.me/+d7jHTPt6NMBhNTRi Мне 36-45 лет - t.me/+pAX1bYlEPzVjZWVi Мне 46-55 лет - t.me/+HryLmBlZHJ4wZjQy Мне 56-65 лет - t.me/+Z-41IQXIxvA2NzJi Мне 70+ лет - t.me/+XrP_rFNe6EE2NzQy Тут нет моего возраста - t.me/+jrBV7m8bYQIwNTEy Узнать больше #реклама О рекламодателе

Иногда вам нужно запустить блок кода с несколькими контекстными менеджерами. Например:

with open('f') as f:
    with open('g') as g:
        with open('h') as h:
            pass
Начиная с Python 2.7 и 3.1, это можно сделать с помощью одного выражения with:

o = open
with o('f') as f, o('g') as g, o('h') as h:
    pass
До этого можно было использовать функцию contextlib.nested:

with nested(o('f'), o('g'), o('h')) as (f, g, h):
    pass
Однако в современных версиях Python эта функция устарела и вызывает предупреждение. Вместо неё рекомендуется использовать более продвинутый инструмент — contextlib.ExitStack. Он позволяет войти в любое количество контекстов в произвольное время, но гарантирует их корректное завершение:

from contextlib import ExitStack

with ExitStack() as stack:
    f = stack.enter_context(o('f'))
    g = stack.enter_context(o('g'))
    other = [
        stack.enter_context(o(filename))
        for filename in filenames
    ]
Это особенно полезно, когда количество контекстных менеджеров неизвестно заранее. 👉@BookPython

UTF-8 — это кодировка с переменной длиной. Один символ может быть закодирован с использованием одного, двух, трёх или четырёх байтов. Это означает, что нельзя начать чтение строки в кодировке UTF-8 с произвольного байта, так как это может случайно разрушить символ:

In : lion = 'Löwe'
In : lion.encode('utf-8')[2:]
Out: b'\xb6we'
In : lion.encode('utf-8')[2:].decode('utf-8')
...
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb6 in position 0: invalid start byte
Также это означает, что для пропуска первых N символов строки их необходимо прочитать и декодировать. Рассчитать смещение заранее невозможно. Однако можно пропустить фиксированное количество байтов, принимая во внимание некоторые особенности. Вот как может быть закодирован символ в UTF-8:

0xxxxxxx
110xxxxx 10xxxxxx
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
Как видно, байт является начальным байтом символа, если его вид не совпадает с 10xxxxxx. Такие байты называются продолжением символа (continuation bytes). Давайте пропустим их:

def cut_bytes(s, n):
    result = s.encode('utf-8')[n:]
    mask = int('11000000', 2)
    conbyte = int('10000000', 2)
    while result[0] and result[0] & mask == conbyte:
        result = result[1:]

    return result.decode('utf-8')
Пример использования:

In : cut_bytes(lion, 2)
Out: 'we'
In : cut_bytes(lion, 1)
Out: 'öwe'
👉@BookPython

Скидки до 70% в Rendez-Vous На сайте Rendez-Vous стартовала финальная распродажа!✨ До конца января у вас есть уникальная возможность приобрести качественную обувь и одежду со скидками до 70%! Это шанс пополнить гардероб элегантными и удобными моделями по выгодным ценам❤️ А еще действует скидка +10% при покупке трех и более товаров и категории обувь, сумки и одежда (кроме топов, маек и футболок). Переходите по ссылке и выбирайте. Перейти на сайт #реклама rendez-vous.onelink.me О рекламодателе

Соединять части пути к файлу удобно с помощью функции os.path.join:

In : dir_path = '/home/vadim/'
In : file_name = 'test.py'
In : os.path.join(dir_path, file_name)
Out: '/home/vadim/test.py'
Это обычно лучше, чем использование строковой конкатенации:

In : dir_path + '/' + file_name
Out: '/home/vadim//test.py'
os.path.join использует правильный разделитель для текущей платформы (например, \ для Windows) и предотвращает появление двойного разделителя (//). Начиная с Python 3.4, можно использовать класс Path из модуля pathlib. (С версии Python 3.6 его экземпляры также можно передавать в os.path.join.) Класс Path поддерживает объединение путей через оператор /:

In : Path('/home/vadim/') / Path('test.py')
Out: PosixPath('/home/vadim/test.py')
👉@BookPython

Дарим подписку на Яндекс Музыку Ответьте на 1 вопрос и Яндекс Музыка для вас и 3-х ваших близких 30 дней бесплатно. Кинопоиск
Дарим подписку на Яндекс Музыку Ответьте на 1 вопрос и Яндекс Музыка для вас и 3-х ваших близких 30 дней бесплатно. Кинопоиск и Яндекс Книги тоже в подписке. Попробуйте сейчас❤️ Попробовать #реклама 18+ music.yandex.ru О рекламодателе Реклама на Яндексе

Подборка Telegram каналов для программистов Системное администрирование 📌 https://t.me/sysadmin_girl Девочка Сисадмин https://t.me/srv_admin_linux Админские угодья https://t.me/linux_srv Типичный Сисадмин https://t.me/linux_odmin Linux: Системный администратор https://t.me/devops_star DevOps Star (Звезда Девопса) https://t.me/i_linux Системный администратор https://t.me/linuxchmod Linux https://t.me/sys_adminos Системный Администратор https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало) https://t.me/sysadminof Книги для админов, полезные материалы https://t.me/i_odmin Все для системного администратора https://t.me/i_odmin_book Библиотека Системного Администратора https://t.me/i_odmin_chat Чат системных администраторов https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др. https://t.me/sysadminoff Новости Линукс Linux 1C разработка 📌 https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С Программирование C++📌 https://t.me/cpp_lib Библиотека C/C++ разработчика https://t.me/cpp_knigi Книги для программистов C/C++ https://t.me/cpp_geek Учим C/C++ на примерах Программирование Python 📌 https://t.me/pythonofff Python академия. Учи Python быстро и легко🐍 https://t.me/BookPython Библиотека Python разработчика https://t.me/python_real Python подборки на русском и английском https://t.me/python_360 Книги по Python Rus Java разработка 📌 https://t.me/BookJava Библиотека Java разработчика https://t.me/java_360 Книги по Java Rus https://t.me/java_geek Учим Java на примерах GitHub Сообщество 📌 https://t.me/Githublib Интересное из GitHub Базы данных (Data Base) 📌 https://t.me/database_info Все про базы данных Мобильная разработка: iOS, Android 📌 https://t.me/developer_mobila Мобильная разработка https://t.me/kotlin_lib Подборки полезного материала по Kotlin Фронтенд разработка 📌 https://t.me/frontend_1 Подборки для frontend разработчиков https://t.me/frontend_sovet Frontend советы, примеры и практика! https://t.me/React_lib Подборки по React js и все что с ним связано Разработка игр 📌 https://t.me/game_devv Все о разработке игр Библиотеки 📌 https://t.me/book_for_dev Книги для программистов Rus https://t.me/programmist_of Книги по программированию https://t.me/proglb Библиотека программиста https://t.me/bfbook Книги для программистов https://t.me/books_reserv Книги для программистов БигДата, машинное обучение 📌 https://t.me/bigdata_1 Data Science, Big Data, Machine Learning, Deep Learning Программирование 📌 https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций https://t.me/coddy_academy Полезные советы по программированию https://t.me/rust_lib Полезный контент по программированию на Rust https://t.me/golang_lib Библиотека Go (Golang) разработчика https://t.me/itmozg Программисты, дизайнеры, новости из мира IT https://t.me/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻 https://t.me/nodejs_lib Подборки по Node js и все что с ним связано https://t.me/ruby_lib Библиотека Ruby программиста QA, тестирование 📌 https://t.me/testlab_qa Библиотека тестировщика Шутки программистов 📌 https://t.me/itumor Шутки программистов Защита, взлом, безопасность 📌 https://t.me/thehaking Канал о кибербезопасности https://t.me/xakep_1 Статьи из "Хакера" Книги, статьи для дизайнеров 📌 https://t.me/ux_web Статьи, книги для дизайнеров Английский 📌 https://t.me/UchuEnglish Английский с нуля Математика 📌 https://t.me/Pomatematike Канал по математике https://t.me/phis_mat Обучающие видео, книги по Физике и Математике Excel лайфхак📌 https://t.me/Excel_lifehack https://t.me/tikon_1 Новости высоких технологий, науки и техники💡 https://t.me/mir_teh Мир технологий (Technology World) Вакансии 📌 https://t.me/sysadmin_rabota Системный Администратор https://t.me/progjob Вакансии в IT

Нативные значения float в Python используют аппаратные возможности вашего компьютера, поэтому любое значение внутренне представлено в виде двоичной дроби. Это означает, что в большинстве случаев вы работаете с приближениями, а не с точными значениями:

In : format(0.1, '.17f')
Out: '0.10000000000000001'
Модуль decimal позволяет использовать десятичную арифметику с произвольной точностью:

In : Decimal(1) / Decimal(3)
Out: Decimal('0.3333333333333333333333333333')
Однако и этого может быть недостаточно:

In [61]: Decimal(1) / Decimal(3) * Decimal(3) == Decimal(1)
Out[61]: False
Для точных вычислений можно использовать fractions, где любое число хранится в виде рационального:

In : Fraction(1) / Fraction(3) * Fraction(3) == Fraction(1)
Out: True
Очевидным ограничением остается то, что иррациональные числа (например, π) все равно будут представлены только в приближенной форме. 👉@BookPython

Тесты могут требовать временные файлы или директории. Для этого отлично подойдет модуль tempfile. Так как временные файлы обычно нужно удалять после использования, tempfile предоставляет как контекстный менеджер, так и простые функции:

import os
import tempfile

with tempfile.TemporaryDirectory() as dir_path:
    open(os.path.join(dir_path, 'a'), 'w').close()
    open(os.path.join(dir_path, 'b'), 'w').close()
    open(os.path.join(dir_path, 'c'), 'w').close()

    assert files_of(dir_path) == ['a', 'b', 'c']
👉@BookPython

Концептуальные офисы в БЦ RUNOVSKY 14 Бизнес-центр «RUNOVSKY 14» предлагает премиальный сервис и разнообразие планировочных р
Концептуальные офисы в БЦ RUNOVSKY 14 Бизнес-центр «RUNOVSKY 14» предлагает премиальный сервис и разнообразие планировочных решений - лоты с площадью от 27 м² с возможностью объединения смежных помещений и высотой потолков 3,2 м. Почему выбирают нас? Расположение: всего 6 минут от Кремля! Панорамное остекление: дает ощущение простора, обилие солнечного света и воздуха. Рестораны и переговорные: всё необходимое для вашего удобства на территории. Интеллектуальный климат: создаёт комфортные условия для продуктивной работы. Консьерж-сервис: администратор всегда поможет встретить гостей, принять посылку или заказать машину. Не упустите возможность стать частью этого уникального пространства! Перейти на сайт #реклама зиккурат.рф О рекламодателе

Чтобы читать строки из stdin в Python до версии 3, использовалась функция raw_input вместо input. Проблема с использованием input заключалась в том, что она выполняла введённую строку как код:

$ echo '[x ** 2 for x in range(10)]' | python2 -c 'print input()'
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
В Python 3 функция input просто читает строку, а raw_input больше не существует. Если вы хотите поддерживать код, работающий как в Python 2, так и в Python 3, можно использовать следующий подход:

from contextlib import suppress

with suppress(NameError):
    input = raw_input
Популярный модуль six уже реализует этот механизм для вас. Он предоставляет функцию input, которая просто читает строку, независимо от версии Python. 👉@BookPython

Неделя выгодных цен на 1-комнатные квартиры в Краснодаре «Родные Просторы» - микрорайон площадью 41,3 га для тех, кому важно
Неделя выгодных цен на 1-комнатные квартиры в Краснодаре «Родные Просторы» - микрорайон площадью 41,3 га для тех, кому важно иметь поблизости необходимые объекты инфраструктуры и комфортную среду для жизни: - квартиры с продуманными планировками - детские площадки, парковая зона, спортивные площадки - магазины, школа, детские сады, поликлиники - видеонаблюдение и система антиобледенения - доступные цены и выгодные условия покупки ✅Платеж по ипотеке от 28 467 руб/мес ✅Рассрочка без удорожания до конца строительства с первоначальным взносом от 30% ✅ПСК 23,157-30,233%. Семейная ипотека от 6% ЖК "Родные Просторы" - это ваш идеальный выбор! Узнать цену Проектная декларация на сайте https://наш.дом.рф/. Застройщик: ООО СЗ ЮГСТРОЙИМПЕРИАЛ. Финансовые услуги оказывает: ПАО "Сбербанк", АО "АЛЬФА-БАНК" и др.. #реклама promo.tochno-rp.ru О рекламодателе

Когда вы создаете кастомный метод __repr__ для объекта, обычно нужно включить представление его атрибутов. Однако важно помнить, что нужно явно вызывать repr(), так как форматирование вызывает str() вместо repr(). Пример простого кода:

class Pair:
    def __init__(self, left, right):
        self.left = left
        self.right = right
        
    def __repr__(self):
        class_name = type(self).__name__
        repr_left = repr(self.left)
        repr_right = repr(self.right)
        return f'{class_name}({repr_left}, {repr_right})'
Проблема возникает, если вы вызываете repr для объекта, который содержит ссылку на самого себя. Это может привести к рекурсии:

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__
    repr_left = repr(self.left)
    repr_right = repr(self.right)
    return f'{class_name}({repr_left}, {repr_right})'
Теперь код работает корректно:

In : p = Pair(1, 2)
In : p.right = p
In : p
Out: Pair(1, ...)
👉@BookPython