Библиотека Python разработчика | Книги по питону
الذهاب إلى القناة على Telegram
Погружение в CPython и архитектуру. Разбираем неочевидное поведение (GIL, Memory), Best Practices (SOLID, DDD) и тонкости Django/FastAPI. Решаем задачи с подвохом и оптимизируем алгоритмы. 🐍 По всем вопросам @evgenycarter РКН clck.ru/3Ko7Hq
إظهار المزيد18 330
المشتركون
-824 ساعات
-357 أيام
-8530 أيام
جاري تحميل البيانات...
القنوات المماثلة
سحابة العلامات
الإشارات الواردة والصادرة
---
---
---
---
---
---
جذب المشتركين
يونيو '26
يونيو '260
في 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 قنوات
| التاريخ | نمو المشتركين | الإشارات | القنوات | |
| 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 | 664 |
| 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 | 695 |
| 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 Питер Новости: Санкт-Петербург / СПБ / ДТП | 636 |
| 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 | 654 |
| 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 | 810 |
| 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 085 |
| 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 Питер Новости: Санкт-Петербург / СПБ / ДТП | 973 |
| 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 | 939 |
| 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 020 |
| 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 | 1 163 |
| 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 | 1 116 |
| 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 | 1 055 |
متاح الآن! بحث تيليغرام 2025 — أهم رؤى العام 
