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

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

前往频道在 Telegram

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

显示更多

📈 Telegram 频道 Библиотека Python разработчика | Книги по питону 的分析概览

频道 Библиотека Python разработчика | Книги по питону (@bookpython) 俄语 语言赛道中的 是活跃参与者。目前社区聚集了 18 328 名订阅者,在 技术与应用 类别中位列第 7 299,并在 俄罗斯 地区排名第 36 904

📊 受众指标与增长动态

невідомо 创建以来,项目保持高速增长,吸引了 18 328 名订阅者。

根据 03 六月, 2026 的最新数据,频道保持稳定运转。过去 30 天订阅人数变化为 -85,过去 24 小时变化为 -8,整体触达仍然可观。

  • 认证状态: 未认证
  • 互动率 (ER): 平均受众互动率为 6.04%。内容发布后 24 小时内通常能获得 2.53% 的反应,占订阅者总量。
  • 帖子覆盖: 每篇帖子平均可获得 1 107 次浏览,首日通常累积 463 次浏览。
  • 互动与反馈: 受众积极参与,单帖平均反应数为 2
  • 主题关注点: 内容集中在 numbers, yield, модуль, none, декоратор 等核心主题上。

📝 描述与内容策略

作者将该频道定位为表达主观观点的平台:
Погружение в CPython и архитектуру. Разбираем неочевидное поведение (GIL, Memory), Best Practices (SOLID, DDD) и тонкости Django/FastAPI. Решаем задачи с подвохом и оптимизируем алгоритмы. 🐍 По всем вопросам @evgenycarter РКН clck.ru/3Ko7Hq

凭借高频更新(最新数据采集于 04 六月, 2026),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。

18 328
订阅者
-824 小时
-357
-8530
吸引订阅者
六月 '26
六月 '26
+1
在0个频道中
五月 '26
+40
在0个频道中
Get PRO
四月 '26
+26
在0个频道中
Get PRO
三月 '26
+31
在0个频道中
Get PRO
二月 '26
+62
在0个频道中
Get PRO
一月 '26
+69
在0个频道中
Get PRO
十二月 '25
+67
在0个频道中
Get PRO
十一月 '25
+97
在31个频道中
Get PRO
十月 '25
+64
在1个频道中
Get PRO
九月 '25
+90
在36个频道中
Get PRO
八月 '25
+60
在0个频道中
Get PRO
七月 '25
+89
在27个频道中
Get PRO
六月 '25
+116
在19个频道中
Get PRO
五月 '25
+119
在44个频道中
Get PRO
四月 '25
+164
在37个频道中
Get PRO
三月 '25
+147
在38个频道中
Get PRO
二月 '25
+178
在31个频道中
Get PRO
一月 '25
+176
在33个频道中
Get PRO
十二月 '24
+158
在34个频道中
Get PRO
十一月 '24
+112
在33个频道中
Get PRO
十月 '24
+139
在29个频道中
Get PRO
九月 '24
+190
在29个频道中
Get PRO
八月 '24
+68
在17个频道中
Get PRO
七月 '24
+56
在0个频道中
Get PRO
六月 '24
+95
在23个频道中
Get PRO
五月 '24
+223
在18个频道中
Get PRO
四月 '24
+174
在0个频道中
Get PRO
三月 '24
+240
在20个频道中
Get PRO
二月 '24
+224
在18个频道中
Get PRO
一月 '24
+287
在23个频道中
Get PRO
十二月 '23
+253
在24个频道中
Get PRO
十一月 '23
+282
在16个频道中
Get PRO
十月 '23
+319
在18个频道中
Get PRO
九月 '23
+342
在0个频道中
Get PRO
八月 '23
+264
在0个频道中
Get PRO
七月 '23
+292
在0个频道中
Get PRO
六月 '23
+211
在0个频道中
Get PRO
五月 '23
+284
在0个频道中
Get PRO
四月 '23
+240
在0个频道中
Get PRO
三月 '23
+419
在0个频道中
Get PRO
二月 '23
+147
在0个频道中
Get PRO
一月 '23
+247
在0个频道中
Get PRO
十二月 '22
+191
在0个频道中
Get PRO
十一月 '22
+174
在0个频道中
Get PRO
十月 '22
+283
在0个频道中
Get PRO
九月 '22
+268
在0个频道中
Get PRO
八月 '22
+287
在0个频道中
Get PRO
七月 '22
+322
在0个频道中
Get PRO
六月 '22
+233
在0个频道中
Get PRO
五月 '22
+258
在0个频道中
Get PRO
四月 '22
+252
在0个频道中
Get PRO
三月 '22
+380
在0个频道中
Get PRO
二月 '22
+207
在0个频道中
Get PRO
一月 '22
+315
在0个频道中
Get PRO
十二月 '21
+211
在0个频道中
Get PRO
十一月 '21
+269
在0个频道中
Get PRO
十月 '21
+326
在0个频道中
Get PRO
九月 '21
+286
在0个频道中
Get PRO
八月 '21
+486
在0个频道中
Get PRO
七月 '21
+420
在0个频道中
Get PRO
六月 '21
+368
在0个频道中
Get PRO
五月 '21
+350
在0个频道中
Get PRO
四月 '21
+387
在0个频道中
Get PRO
三月 '21
+568
在0个频道中
Get PRO
二月 '21
+572
在0个频道中
Get PRO
一月 '21
+777
在0个频道中
Get PRO
十二月 '20
+18 545
在0个频道中
日期
订阅者增长
提及
频道
04 六月+1
03 六月0
02 六月0
01 六月0
频道帖子
Условное использование менеджеров контекста обычно доставляет неудобства: нельзя просто разместить with внутри блока if, не заключив туда весь блок with. Это часто приводит к дублированию кода:

def print_whole_file(
    *,
    path: Optional[str] = None,
    file_obj: Optional[TextIO] = None
):
    assert path or file_obj

    if path:
        with open(path) as f:
            print(f.read(), end='')
    else:
        print(file_obj.read(), end='')
Способ борьбы с этой проблемой — использовать ExitStack и вызывать enter_context внутри if:

def print_whole_file(
    *,
    path: Optional[str] = None,
    file_obj: Optional[TextIO] = None
):
    assert path or file_obj

    with ExitStack() as stack:
        if path:
            file_obj = stack.enter_context(
                open(path)
            )

        print(file_obj.read(), end='')
Однако более очевидный способ достичь того же — использовать тривиальные менеджеры контекста, которые ничего не делают, когда они не нужны, вместо «настоящих». Начиная с Python 3.7, их можно получить с помощью contextlib.nullcontext:

def print_whole_file(
    *,
    path: Optional[str] = None,
    file_obj: Optional[TextIO] = None
):
    assert path or file_obj

    if path:
        context = open(path)
    else:
        context = nullcontext(file_obj)

    with context as f:
        print(f.read(), end='')
📲 Мы в MAX 👉@BookPython

2
В Python функция range() определяет все целые числа в полуоткрытом интервале. То есть range(2, 10) математически означает [2, 10), или, говоря на языке Python: [2, 3, 4, 5, 6, 7, 8, 9]. Несмотря на асимметрию, это не ошибка и не случайность. В этом есть логика: такой подход позволяет "склеивать" два соседних интервала без риска ошибиться на единицу: [a, c) = [a, b) + [b, c) Для сравнения, если бы использовались закрытые интервалы, получалось бы так: [a, c] = [a, b] + [b+1, c] Эта же идея объясняет, почему индексация начинается с нуля: [0, N) содержит ровно N элементов. Эдсгер Дейкстра написал на эту тему отличную статью ещё в 1982 году. 📲 Мы в MAX 👉@BookPython
697
3
В списковых включениях (list comprehensions) может быть больше одного цикла for и условия if: In : [(x, y) for x in range(3) for y in range(3)] Out: [ (0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2) ] In : [ (x, y) for x in range(3) for y in range(3) if x != 0 if y != 0 ] Out: [(1, 1), (1, 2), (2, 1), (2, 2)] Кроме того, любое выражение внутри for и if может использовать все переменные, которые были определены ранее: In : [ (x, y) for x in range(3) for y in range(x + 2) if x != y ] Out: [ (0, 1), (1, 0), (1, 2), (2, 0), (2, 1), (2, 3) ] Можно смешивать if и for в любом порядке: In : [ (x, y) for x in range(5) if x % 2 for y in range(x + 2) if x != y ] Out: [ (1, 0), (1, 2), (3, 0), (3, 1), (3, 2), (3, 4) ] 📲 Мы в MAX 👉@BookPython
720
4
🚀 Подборка полезных IT каналов в Max Системное администрирование, DevOps 📌 https://max.ru/i_odmin Все для системного администратора https://max.ru/bash_srv Bash Советы https://max.ru/sysadminof Книги для админов, полезные материалы https://max.ru/i_odmin_book Библиотека Системного Администратора https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др. https://max.ru/tipsysdmin Типичный Сисадмин Excel лайфхак 📌 https://t.me/Excel_lifehack Excel лайфхак 1C разработка 📌 https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С Программирование C++📌 https://max.ru/cpp_lib Библиотека C/C++ разработчика Программирование Go📌 https://max.ru/golang_lib Библиотека Go (Golang) разработчика Программирование React📌 https://max.ru/react_lib React Программирование Python 📌 https://max.ru/python_of Python академия. https://max.ru/BookPython Библиотека Python разработчика Java разработка 📌 https://max.ru/bookjava Библиотека Java разработчика GitHub Сообщество 📌 https://max.ru/githublib Интересное из GitHub Базы данных (Data Base) 📌 https://max.ru/database_info Все про базы данных Фронтенд разработка 📌 https://max.ru/frontend_1 Подборки для frontend разработчиков Библиотеки 📌 https://max.ru/programmist_of Книги по программированию https://max.ru/proglb Библиотека программиста https://max.ru/bfbook Книги для программистов Программирование 📌 https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT https://max.ru/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻 Шутки программистов 📌 https://max.ru/itumor Шутки программистов Защита, взлом, безопасность 📌 https://max.ru/thehaking Канал о кибербезопасности https://max.ru/xakkep_1 Хакер Free Книги, статьи для дизайнеров 📌 https://max.ru/odesigners Статьи, книги для дизайнеров Математика 📌 https://max.ru/Pomatematike Канал по математике https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике Вакансии 📌 https://max.ru/progjob Вакансии в IT Мир технологий 📌 https://max.ru/mir_teh Канал для любознательных Бонус 📌 https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга https://max.ru/mockva_life Свежие новости Москвы https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП
654
5
Оператор in можно использовать с генераторами: x 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. 📲 Мы в MAX 👉@BookPython
667
6
В Python можно переопределить оператор квадратных скобок ([]), реализовав магический метод __getitem__. Вот так можно создать объект, который виртуально содержит бесконечное количество повторяющихся элементов: class Cycle: def __init__(self, lst): self._lst = lst def __getitem__(self, index): return self._lst[index % len(self._lst)] print(Cycle(['a', 'b', 'c'])[100]) # 'b' Необычность здесь в том, что оператор [] поддерживает особый синтаксис. Его можно использовать не только так — [2], но и так — [2:10], [2:10:2], [2::2] или даже [:]. Обычно это интерпретируется как [start:stop:step], но вы можете задать любую логику для своих объектов. Что же передаётся в параметр index метода __getitem__, если использовать такой синтаксис? Для этого в Python существуют объекты slice. class Inspector: def __getitem__(self, index): print(index) Inspector()[1] # 1 Inspector()[1:2] # slice(1, 2, None) Inspector()[1:2:3] # slice(1, 2, 3) Inspector()[:] # slice(None, None, None) Можно даже комбинировать кортежи и срезы: Inspector()[:, 0, :] # (slice(None, None, None), 0, slice(None, None, None)) Объект slice сам по себе ничего не делает — он просто хранит атрибуты start, stop и step: s = slice(1, 2, 3) s.start # 1 s.stop # 2 s.step # 3 📲 Мы в MAX 👉@BookPython
819
7
Python предоставляет мощную библиотеку для работы с датой и временем — datetime. Интересная особенность в том, что объекты datetime имеют специальный интерфейс для поддержки часовых поясов (а именно атрибут tzinfo), но сам модуль реализует этот интерфейс лишь частично, оставляя остальную работу другим модулям. Наиболее популярный модуль для этой задачи — pytz. Хитрость в том, что pytz не полностью соответствует интерфейсу tzinfo. В документации pytz это указано уже в первых строках: «Эта библиотека отличается от задокументированного Python API для реализаций tzinfo». Вы не можете использовать объекты часовых поясов pytz напрямую в качестве tzinfo. Если попробовать, можно получить совершенно неожиданные результаты: In : paris = pytz.timezone('Europe/Paris') In : str(datetime(2017, 1, 1, tzinfo=paris)) Out: '2017-01-01 00:00:00+00:09' Обратите внимание на смещение +00:09. Правильное использование pytz выглядит так: In : str(paris.localize(datetime(2017, 1, 1))) Out: '2017-01-01 00:00:00+01:00' Также после любых арифметических операций с датами рекомендуется нормализовать объект datetime на случай изменения смещения (например, на границе перехода на летнее время): In : new_time = time + timedelta(days=2) In : str(new_time) Out: '2018-03-27 00:00:00+01:00' In : str(paris.normalize(new_time)) Out: '2018-03-27 01:00:00+02:00' Начиная с Python 3.6, рекомендуется использовать dateutil. tz вместо pytz. Он полностью совместим с tzinfo, может напрямую передаваться в атрибут tzinfo, не требует нормализации, хотя работает немного медленнее. 📲 Мы в MAX 👉@BookPython
1 150
8
Можно добавлять символы Unicode в строковый литерал не только по их номеру, но и по имени. >>> '\N{EM DASH}' '—' >>> '\u2014' '—' Это также совместимо с f-строками: >>> width = 800 >>> f'Width \N{EM DASH} {width}' 'Width — 800' 📲 Мы в MAX 👉@BookPython
1 098
9
🚀 Подборка полезных IT каналов в Max Системное администрирование, DevOps 📌 https://max.ru/i_odmin Все для системного администратора https://max.ru/bash_srv Bash Советы https://max.ru/sysadminof Книги для админов, полезные материалы https://max.ru/i_odmin_book Библиотека Системного Администратора https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др. https://max.ru/tipsysdmin Типичный Сисадмин Excel лайфхак 📌 https://t.me/Excel_lifehack Excel лайфхак 1C разработка 📌 https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С Программирование C++📌 https://max.ru/cpp_lib Библиотека C/C++ разработчика Программирование Go📌 https://max.ru/golang_lib Библиотека Go (Golang) разработчика Программирование React📌 https://max.ru/react_lib React Программирование Python 📌 https://max.ru/python_of Python академия. https://max.ru/BookPython Библиотека Python разработчика Java разработка 📌 https://max.ru/bookjava Библиотека Java разработчика GitHub Сообщество 📌 https://max.ru/githublib Интересное из GitHub Базы данных (Data Base) 📌 https://max.ru/database_info Все про базы данных Фронтенд разработка 📌 https://max.ru/frontend_1 Подборки для frontend разработчиков Библиотеки 📌 https://max.ru/programmist_of Книги по программированию https://max.ru/proglb Библиотека программиста https://max.ru/bfbook Книги для программистов Программирование 📌 https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT https://max.ru/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻 Шутки программистов 📌 https://max.ru/itumor Шутки программистов Защита, взлом, безопасность 📌 https://max.ru/thehaking Канал о кибербезопасности https://max.ru/xakkep_1 Хакер Free Книги, статьи для дизайнеров 📌 https://max.ru/odesigners Статьи, книги для дизайнеров Математика 📌 https://max.ru/Pomatematike Канал по математике https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике Вакансии 📌 https://max.ru/progjob Вакансии в IT Мир технологий 📌 https://max.ru/mir_teh Канал для любознательных Бонус 📌 https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга https://max.ru/mockva_life Свежие новости Москвы https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП
980
10
Если вы хотите, чтобы объекты класса имели автоинкрементируемый ID, это можно сделать, отслеживая текущий ID в атрибуте класса: class Task: _task_id = 0 def __init__(self): self._id = self._task_id type(self)._task_id += 1 Учтите, что нельзя писать self._task_id += 1. Это создаст атрибут _task_id в экземпляре, а не в классе. Вместо этого стоит использовать фабричный метод, чтобы сделать код красивее: class Task: _task_id = 0 def __init__(self, task_id): self._id = task_id @classmethod def create(cls): obj = cls(cls._task_id) cls._task_id += 1 return obj Эта версия также проще для тестирования, так как можно легко задать любой пользовательский ID. 📲 Мы в MAX 👉@BookPython
947
11
Оператор break подавляет исключение, если используется в блоке finally, даже когда блок except отсутствует: for i in range(10): try: 1 / i finally: print('finally') break print('after try') print('after while') Вывод: finally after while То же самое верно и для continue, однако его нельзя использовать в блоке finally до версии Python 3.8: SyntaxError: 'continue' not supported inside 'finally' clause 📲 Мы в MAX 👉@BookPython
1 024
12
В asyncio распространённая практика для планирования выполнения кода с задержкой — создать задачу, которая делает await asyncio.sleep(x): import asyncio async def do(n=0): print(n) await asyncio.sleep(1) loop.create_task(do(n + 1)) loop.create_task(do(n + 1)) loop = asyncio.get_event_loop() loop.create_task(do()) loop.run_forever() Однако создание новой задачи может быть затратным и не требуется, если вы не собираетесь выполнять асинхронные операции (как в функции do из примера). Другой способ сделать это — использовать функции loop.call_later и loop.call_at, которые планируют вызов асинхронного колбэка: import asyncio def do(n=0): print(n) loop = asyncio.get_event_loop() loop.call_later(1, do, n+1) loop.call_later(1, do, n+1) loop = asyncio.get_event_loop() do() loop.run_forever() 📲 Мы в MAX 👉@BookPython
1 129
13
Если декоратор, который вы пишете, становится слишком сложным, имеет смысл преобразовать его из функции в класс с методом __call__. class SavingOrig: def __init__(self, another_decorator): self._another = another_decorator def __call__(self, f): decorated = self._another(f) if hasattr(f, 'orig'): decorated.orig = f.orig else: decorated.orig = f return decorated saving_orig = SavingOrig Последняя строка позволяет одновременно дать классу имя в стиле CamelCase и сохранить имя декоратора в стиле snake_case. 📲 Мы в MAX 👉@BookPython
1 181
14
Ты можешь использовать любой объект в качестве ключа словаря в Python, если он реализует метод __hash__. Этот метод может возвращать любое целое число при одном важном условии: равные объекты должны иметь одинаковые хэши (обратное не обязательно). Также следует избегать использования изменяемых объектов в качестве ключей, потому что если объект изменится и перестанет быть равным самому себе в прошлом состоянии, его больше нельзя будет найти в словаре. Есть ещё один странный момент, который может удивить при отладке или написании юнит-тестов: class A: def __init__(self, x): self.x = x def __hash__(self): return self.x hash(A(2)) # 2 hash(A(1)) # 1 hash(A(0)) # 0 hash(A(-1)) # -2 (!) hash(A(-2)) # -2 В CPython значение -1 зарезервировано для внутренних состояний ошибок, поэтому оно автоматически преобразуется в -2. 📲 Мы в MAX 👉@BookPython
1 119
15
В Python 3, после выхода из блока except переменные, в которых хранятся перехваченные исключения, удаляются из locals(), даже если они существовали раньше: >>> e = 2 >>> try: ... 1/0 ... except Exception as e: ... pass ... >>> e Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'e' is not defined Если нужно сохранить ссылку на исключение, используйте другую переменную: >>> error = None >>> try: ... 1/0 ... except Exception as e: ... error = e ... >>> error ZeroDivisionError('division by zero',) В Python 2 это правило не действует. 📲 Мы в MAX 👉@BookPython
1 184
16
Некоторые модули Python компилируются непосредственно в сам интерпретатор. Они называются встроенными модулями (built-in), и их не следует путать со стандартной библиотекой. Чтобы получить полный список таких модулей, можно использовать sys.builtin_module_names. Примеры таких модулей — sys, gc, time и т. д. Обычно вам не важно, является ли модуль встроенным или нет; однако стоит иметь в виду, что import сначала ищет модуль среди встроенных. Поэтому будет загружен встроенный модуль sys, даже если в текущей директории есть файл sys.py. С другой стороны, если, например, в текущей директории есть файл datetime.py, он действительно может быть загружен вместо стандартного модуля datetime. 📲 Мы в MAX 👉@BookPython
1 165
17
collections.defaultdict позволяет создать словарь, который возвращает значение по умолчанию, если запрашиваемого ключа нет (вместо того чтобы выбрасывать исключение KeyError). При создании defaultdict необходимо указывать не само значение по умолчанию, а фабрику для его создания. Это позволяет создавать словари с бесконечным числом вложенных уровней, что дает возможность писать что-то вроде d[a][b][c]...[z]. >>> def infinite_dict(): ... return defaultdict(infinite_dict) ... >>> d = infinite_dict() >>> d[1][2][3][4] = 10 >>> dict(d[1][2][3][5]) {} Такое поведение называется “автовивификация” (от англ. autovivification) — термин пришёл из языка Perl. 📲 Мы в MAX 👉@BookPython
1 216
18
Скажем, вы хотите получить первые N элементов итерируемого объекта. Прямолинейный способ — использовать islice: from itertools import islice def fib(): a, b = 0, 1 while True: yield b a, b = b, (a + b) list(islice(fib(), 5)) # Результат: [1, 1, 2, 3, 5] Если вы также хотите получить индексы элементов, можно применить enumerate: list(enumerate(islice(fib(), 5))) # Результат: [(0, 1), (1, 1), (2, 2), (3, 3), (4, 5)] Другой способ сделать это — использовать zip и range, что может показаться более читаемым: list(zip(range(5), fib())) # Результат: [(0, 1), (1, 1), (2, 2), (3, 3), (4, 5)] 📲 Мы в MAX 👉@BookPython
0
19
Когда вы используете fork для создания нового процесса, текущее состояние генератора случайных чисел (включая seed) копируется в дочерний процесс. Это может привести к тому, что разные процессы будут генерировать одинаковые «случайные» значения. Чтобы избежать этого, необходимо вручную вызывать random.seed() в каждом процессе. Однако, если вы используете модуль multiprocessing, он уже автоматически выполняет это за вас. Пример: import multiprocessing import random import os import sys def test(a): print(random.choice(a), end=' ') a = [1, 2, 3, 4, 5] # Вызов в основном процессе for _ in range(5): test(a) print() # Вызов с multiprocessing.Process for _ in range(5): p = multiprocessing.Process( target=test, args=(a,) ) p.start() p.join() print() # Вызов с использованием os.fork for _ in range(5): pid = os.fork() if pid == 0: test(a) sys.exit() else: os.wait() print() Вывод будет примерно такой: 4 4 4 5 5 1 4 1 3 3 2 2 2 2 2 Причём, начиная с Python 3.7, os.fork также использует механизм at_fork hook, который переинициализирует генератор случайных чисел, как и multiprocessing. Так что в Python 3.7+ вывод кода выше может быть таким: 1 2 2 1 5 4 4 4 5 5 2 4 1 3 1 📲 Мы в MAX 👉@BookPython
0
20
Сортировка списка с элементами None может быть затруднительной: In [1]: data = [ ...: dict(a=1), ...: None, ...: dict(a=-3), ...: dict(a=2), ...: None, ...: ] Попытка сортировки приведёт к ошибке: In [2]: sorted(data, key=lambda x: x['a']) --------------------------------------------------------------------------- TypeError: 'NoneType' object is not subscriptable Можно удалить None перед сортировкой, а затем добавить их обратно (в конец или начало списка — в зависимости от задачи): In [3]: sorted( ...: (d for d in data if d is not None), ...: key=lambda x: x['a'] ...: ) + [ ...: d for d in data if d is None ...: ] Out[3]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None] Это громоздко. Лучше использовать более сложную функцию ключа: In [4]: sorted(data, key=lambda x: float('inf') if x is None else x['a']) Out[4]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None] Если тип данных не поддерживает бесконечность (float('inf')), можно сортировать кортежи: In [5]: sorted(data, key=lambda x: (1, None) if x is None else (0, x['a'])) Out[5]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None] 📲 Мы в MAX 👉@BookPython
0