bookpython | Unsorted

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

19203

Полезные материалы для питониста по Фреймворкам Django, Flask, FastAPI, Pyramid, Tornado и др. По всем вопросам @evgenycarter РКН clck.ru/3Ko7Hq

Subscribe to a channel

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

Прямой доступ к атрибутам объекта может быть не самой лучшей идеей. Если клиенты взаимодействуют с объектом через методы, вы всегда можете изменить способ обработки каждого запроса, в то время как при прямом доступе к атрибутам это может быть невозможно.

Разные языки решают эту проблему по-разному. В Ruby синтаксически невозможно получить прямой доступ к атрибуту: obj.x — это вызов метода x. В Java рекомендуется делать все атрибуты приватными и писать тривиальные геттеры, например: public int getX() { return this.x; }.

Python предлагает решение, которое в некотором роде похоже на то, что есть в Ruby. Вы можете определить свойство (property), чтобы obj.x вызывал метод вместо прямого возврата атрибута x.


class Example:
def __init__(self, x):
self._x = x

@property
def x(self):
return self._x


📲 Мы в MAX

👉@BookPython

Читать полностью…

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

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


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)


📲 Мы в MAX

👉@BookPython

Читать полностью…

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

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


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
]


Это особенно полезно, когда количество контекстных менеджеров неизвестно заранее.

📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Нативные значения 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


Очевидным ограничением остается то, что иррациональные числа (например, π) все равно будут представлены только в приближенной форме.

📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Продвижение в Telegram с помощью Яндекс Директа

⚡Запустите продвижение в телеграм-каналах и привлекайте целевую аудиторию

📱 Таргетинг по тематикам, регионам и каналам в Telegram

Попробовать

#реклама
yandex.ru

О рекламодателе

Читать полностью…

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

27 ноября собираемся на Pytup: митап Яндекса для Python-разработчиков и ML-инженеров 🚀

Присоединяйтесь в Екатеринбурге или онлайн, чтобы в неформальной обстановке поговорить о Python, машинном обучении и технологиях, которые двигают индустрию вперед.

В программе выступлений:

> Арсений Саблин, разработчик системы контроля качества умных устройств на производстве (Яндекс Алиса), поделится, как используется Python при тестировании станции с Алисой;

> Никита Улько, техлид VK Tech, разберет чистую архитектуру с практической точки зрения: за что ее ценят и как гибко применять ее принципы, фокусируясь на решении конкретных проблем;

> Егор Гордовский, технический менеджер проектов Yandex Cloud, расскажет о сложном техническом организме, помогающем превратить код в работающий сервис — дата-центре.

Помимо докладов участников в Екатеринбурге ждет дискуссия Snake Pit, а также соревнования по классической «Змейке» и гонки на игрушечных роботах-доставщиках.

📅 27 ноября в 17.00 (по Екб)
📍 Екатеринбург (креативный кластер «Домна») + онлайн

Регистрация на митап

Читать полностью…

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

Функция itertools.chain позволяет объединить несколько итерируемых объектов, чтобы работать с ними, как с единым целым:


from itertools import chain

print(list(chain(['a', 'b'], range(3), set('xyz'))))
# Вывод: ['a', 'b', 0, 1, 2, 'x', 'z', 'y']


Иногда нужно проверить, пуст ли генератор (точнее, исчерпан ли он). Для этого можно попытаться получить следующий элемент с помощью next(). Если элемент есть, его нужно вернуть обратно в генератор, но сделать это напрямую невозможно. Однако можно «приклеить» его обратно с помощью chain:


from itertools import chain

def sum_of_odd(gen):
try:
first = next(gen) # Пытаемся получить первый элемент
except StopIteration:
raise ValueError('Empty generator') # Если генератор пуст, выбрасываем исключение

# Используем chain для возврата первого элемента и объединения с остальными
return sum(
x for x in chain([first], gen)
if x % 2 == 1 # Суммируем только нечетные числа
)


Пример использования:


print(sum_of_odd(x for x in range(1, 6))) # Вывод: 9 (1 + 3 + 5)
print(sum_of_odd(x for x in range(2, 3))) # Вывод: 0 (нет нечетных чисел)
print(sum_of_odd(x for x in range(2, 2))) # ValueError: Empty generator


📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Метод format в Python для строк — мощный инструмент, поддерживающий множество возможностей, о которых вы, возможно, даже не знали. Каждый заменяемый плейсхолдер ({...}) может содержать три части: имя поля, преобразование и спецификацию формата.

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


>>> '{}'.format(42)
'42'
>>> '{1}'.format(1, 2)
'2'
>>> '{y}'.format(x=1, y=2)
'2'


Преобразование позволяет указать, что вместо str() следует использовать repr() (или ascii()) при преобразовании объектов в строки:


>>> '{!r}'.format(datetime.now())
'datetime.datetime(2018, 5, 3, 23, 48, 49, 157037)'
>>> '{}'.format(datetime.now())
'2018-05-03 23:49:01.060852'


Спецификация формата задаёт, как значения будут представлены:


>>> '{:+,}'.format(1234567)
'+1,234,567'
>>> '{:>19}'.format(1234567)
' 1234567'


Эта спецификация может быть применена и к отдельному объекту с помощью функции format (не метода str):


>>> format(5000000, '+,')
'+5,000,000'


Функция format вызывает метод __format__ объекта, поэтому вы можете изменить его поведение для своих типов.

📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Иногда нужно создать функцию на основе более универсальной. Например, у функции int() есть параметр base, который можно зафиксировать, чтобы получить новую функцию base2:


>>> int("10")
10
>>> int("10", 2)
2
>>> def base2(x):
... return int(x, 2)
...
>>> base2("10")
2


Для более точной и семантически понятной реализации можно использовать functools.partial:


from functools import partial

base2 = partial(int, base=2)


Это удобно, когда нужно передать функцию в качестве аргумента в другую функцию высшего порядка, но с заблокированными значениями некоторых аргументов:


>>> list(map(partial(int, base=2), ["1", "10", "100"]))
[1, 2, 4]


Без использования partial пришлось бы писать код так:


>>> list(map(lambda x: int(x, base=2), ["1", "10", "100"]))
[1, 2, 4]


📲 Мы в MAX

👉@BookPython

Читать полностью…

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

📌 О представлении данных в байтах в Python

Когда мы храним данные в памяти или на устройстве хранения, их необходимо представить в виде байтов. Python позволяет работать с абстракцией данных, не задумываясь об их байтовом представлении. Однако при записи строки в файл мы фактически работаем с физической структурой данных.

Чтобы записать символы в файл, их нужно преобразовать в байты — это называется кодированием (encoding). Когда вы читаете байты из файла и хотите преобразовать их в понятные символы, этот процесс называется декодированием (decoding).

🔤 Кодировки и их применение

Существует множество методов кодирования. Один из самых популярных — Unicode, но сам по себе Unicode не является кодировкой в традиционном смысле. Unicode определяет соответствие между символами и их числовыми кодами. Например, 🐍 имеет код 128 013.

Однако, чтобы записать числа в файл, нужна настоящая кодировка. Unicode обычно используется с utf-8, которая (в большинстве случаев) является кодировкой по умолчанию в Python. При чтении из файла Python автоматически декодирует данные, используя utf-8.

Если вы хотите использовать другую кодировку, просто укажите её с помощью параметра encoding= в функции open. А чтобы работать с "чистыми" байтами, добавьте символ b к режиму открытия файла.

Пример:


# Кодирование строки в файл
with open('example.txt', 'w', encoding='utf-8') as f:
f.write('Привет, мир!')

# Чтение в байтовом режиме
with open('example.txt', 'rb') as f:
data = f.read()
print(data) # Вывод: b'\xd0\x9f\xd1\x80\xd0\xb8...'


📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Модуль multiprocessing в Python: потоки против процессов

Модуль multiprocessing позволяет создавать не только процессы, но и потоки. Однако стоит помнить о главной особенности CPython — GIL (Global Interpreter Lock). Этот механизм блокирует выполнение байт-кода Python несколькими потоками одновременно.

Это означает, что потоки полезны в основном в случаях, когда программа выполняет операции, не связанные с Python-интерпретатором, например, ожидание ввода-вывода (IO). К примеру, загрузка трёх различных статей из Википедии будет одинаково эффективной как с потоками, так и с процессами. Причём результат в три раза быстрее по сравнению с выполнением задачи в одном процессе:


from multiprocessing import Pool
from multiprocessing.pool import ThreadPool
import requests

def download_wiki_article(article):
url = 'http://de.wikipedia.org/wiki/'
return requests.get(url + article)

process_pool = Pool(3)
thread_pool = ThreadPool(3)

thread_pool.map(download_wiki_article, ['a', 'b', 'c'])
# ~376 ms

process_pool.map(download_wiki_article, ['a', 'b', 'c'])
# ~373 ms

[download_wiki_article(a) for a in ['a', 'b', 'c']]
# ~1.09 s


Однако использование потоков для задач, нагружающих CPU, практически бессмысленно:


import math
from multiprocessing import Pool
from multiprocessing.pool import ThreadPool

def f(x):
return len(str(math.factorial(x)))

process_pool = Pool(4)
thread_pool = ThreadPool(4)
inputs = [i ** 2 for i in range(100, 130)]

[f(x) for x in inputs]
# ~1.48 s

thread_pool.map(f, inputs)
# ~1.48 s

process_pool.map(f, inputs)
# ~478 ms


При задачах, требующих интенсивных вычислений, использование процессов вместо потоков даст значительный прирост производительности благодаря распределению нагрузки между несколькими ядрами процессора.

📲 Мы в MAX

👉@BookPython

Читать полностью…

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

🚀 Подборка Telegram каналов для программистов

Системное администрирование, DevOps 📌
/channel/bash_srv Bash Советы
/channel/win_sysadmin Системный Администратор Windows
/channel/sysadmin_girl Девочка Сисадмин
/channel/srv_admin_linux Админские угодья
/channel/linux_srv Типичный Сисадмин
/channel/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
/channel/linux_odmin Linux: Системный администратор
/channel/devops_star DevOps Star (Звезда Девопса)
/channel/i_linux Системный администратор
/channel/linuxchmod Linux
/channel/sys_adminos Системный Администратор
/channel/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
/channel/sysadminof Книги для админов, полезные материалы
/channel/i_odmin Все для системного администратора
/channel/i_odmin_book Библиотека Системного Администратора
/channel/i_odmin_chat Чат системных администраторов
/channel/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
/channel/sysadminoff Новости Линукс Linux

1C разработка 📌
/channel/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
/channel/DevLab1C 1С:Предприятие 8
/channel/razrab_1C 1C Разработчик
/channel/buh1C_prog 1C Программист | Бухгалтерия и Учёт
/channel/rabota1C_rus Вакансии для программистов 1С

Программирование C++📌
/channel/cpp_lib Библиотека C/C++ разработчика
/channel/cpp_knigi Книги для программистов C/C++
/channel/cpp_geek Учим C/C++ на примерах

Программирование Python 📌
/channel/pythonofff Python академия.
/channel/BookPython Библиотека Python разработчика
/channel/python_real Python подборки на русском и английском
/channel/python_360 Книги по Python

Java разработка 📌
/channel/BookJava Библиотека Java разработчика
/channel/java_360 Книги по Java Rus
/channel/java_geek Учим Java на примерах

GitHub Сообщество 📌
/channel/Githublib Интересное из GitHub

Базы данных (Data Base) 📌
/channel/database_info Все про базы данных

Мобильная разработка: iOS, Android 📌
/channel/developer_mobila Мобильная разработка
/channel/kotlin_lib Подборки полезного материала по Kotlin
/channel/androidspb Разработка под Android: Kotlin, Java.

Фронтенд разработка 📌
/channel/frontend_1 Подборки для frontend разработчиков
/channel/frontend_sovet Frontend советы, примеры и практика!
/channel/React_lib Подборки по React js и все что с ним связано

Разработка игр 📌
/channel/game_devv Все о разработке игр

Библиотеки 📌
/channel/book_for_dev Книги для программистов Rus
/channel/programmist_of Книги по программированию
/channel/proglb Библиотека программиста
/channel/bfbook Книги для программистов

БигДата, машинное обучение 📌
/channel/bigdata_1 Big Data, Machine Learning

Программирование 📌
/channel/bookflow Лекции, видеоуроки, доклады с IT конференций
/channel/rust_lib Полезный контент по программированию на Rust
/channel/golang_lib Библиотека Go (Golang) разработчика
/channel/itmozg Программисты, дизайнеры, новости из мира IT
/channel/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻
/channel/nodejs_lib Подборки по Node js и все что с ним связано
/channel/ruby_lib Библиотека Ruby программиста
/channel/lifeproger Жизнь программиста. Авторский канал.

QA, тестирование 📌
/channel/testlab_qa Библиотека тестировщика

Шутки программистов 📌
/channel/itumor Шутки программистов

Защита, взлом, безопасность 📌
/channel/thehaking Канал о кибербезопасности
/channel/xakep_2 Хакер Free

Книги, статьи для дизайнеров 📌
/channel/ux_web Статьи, книги для дизайнеров

Математика 📌
/channel/Pomatematike Канал по математике
/channel/phis_mat Обучающие видео, книги по Физике и Математике
/channel/matgeoru Математика | Геометрия | Логика

Excel лайфхак📌
/channel/Excel_lifehack

/channel/mir_teh Мир технологий (Technology World)

Вакансии 📌
/channel/sysadmin_rabota Системный Администратор
/channel/progjob Вакансии в IT

Читать полностью…

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

Когда вам нужно очистить список в Python, вы, скорее всего, используете lst = []. Однако на самом деле вы просто создаёте новый пустой список и присваиваете его переменной lst, а все другие переменные, которые ссылаются на исходный список, продолжают хранить его содержимое.

Пример:


lst = [1, 2, 3]
lst2 = lst
lst = []
print(lst2) # [1, 2, 3]


Хотя это кажется очевидным, правильное решение стало доступно только с введением метода lst.clear() в Python 3.3.

До этого для очистки списка приходилось использовать:
- del lst[:], или
- lst[:] = [].

Оба варианта работают, поскольку срезы позволяют модифицировать часть списка. Если вы берёте срез [:], он охватывает весь список.

Теперь же lst.clear() является более читаемым и современным решением.

📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Как узнать размер генератора в Python?

В Python часто возникает задача определить размер генератора без необходимости извлечения всех его значений. Это полезно, если вы работаете с большими потоками данных и хотите избежать избыточного расхода памяти.

Пример с len()
Некоторые итераторы, такие как range, поддерживают вызов len():


len(range(10000)) # 10000


Однако генераторы не имеют длины, и попытка вызвать len() вызовет ошибку:


gen = (x ** 2 for x in range(10000))
len(gen) # TypeError: object of type 'generator' has no len()


Стандартное решение: преобразование в список
Один из способов получить размер генератора — это преобразовать его в список:


gen = (x ** 2 for x in range(10000))
print(len(list(gen))) # 10000


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

Более эффективный подход: подсчёт с помощью sum
Чтобы избежать лишнего расхода памяти, можно подсчитать количество элементов в генераторе с использованием sum():


gen = (x ** 2 for x in range(10000))
print(sum(1 for _ in gen)) # 10000


Этот метод обходит генератор "лениво", не создавая дополнительных списков, что делает его идеальным для работы с большими потоками данных.

Резюме
- Используйте len() только для итераторов, поддерживающих его (например, range).
- Для генераторов избегайте преобразования в список, если важна экономия памяти.
- Используйте sum(1 for _ in gen) для эффективного подсчёта элементов генератора.

📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Распаковка параметров функций в Python 2 и 3

В Python 2 существовала интересная возможность распаковывать параметры функций прямо в их определении. Пример:


def between(x, (start, stop)):
return start < x < stop

interval = (5, 10)
print(between(2, interval)) # False
print(between(7, interval)) # True


Более того, это работало даже рекурсивно:


def determinant_2_x_2(((a, b), (c, d))):
return a * d - c * b

matrix = [
(1, 2),
(3, 4),
]
print(determinant_2_x_2(matrix)) # -2


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


def determinant_2_x_2(matrix):
row1, row2 = matrix
a, b = row1
c, d = row2
return a * d - c * b

matrix = [
(1, 2),
(3, 4),
]
print(determinant_2_x_2(matrix)) # -2


Удаление этой функциональности сделало код более явным и читаемым, но для любителей компактности Python 2 по-прежнему вызывает лёгкую ностальгию.

📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Выбирать бытовую технику больше не сложно!

А создавать уют в доме — исключительно приятно. Канал Techscanner — ваш надежный гид в мире комфорта и умного дома.

Подписывайтесь: t.me/+AT18pK1DKCRjY2Ji

Здесь вы найдете:
Советы по выбору техники, которая упростит вашу жизнь.
Обзоры и сравнения простым языком и на личном опыте.
Идеи для уюта, чтобы ваш дом был не только функциональным, но и стильным.
Лайфхаки для упрощения домашних дел.

Читайте Techscanner, чтобы ваш дом стал умнее, уютнее и удобнее!

Подписаться

#реклама
О рекламодателе

Читать полностью…

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

Когда корутина 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 устанавливает внутренний флаг перед тем, как вернуть управление.

📲 Мы в MAX

👉@BookPython

Читать полностью…

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

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'


📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Тесты могут требовать временные файлы или директории. Для этого отлично подойдет модуль 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']


📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Когда вы создаете кастомный метод __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, ...)


📲 Мы в MAX

👉@BookPython

Читать полностью…

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

В Python блок else можно использовать не только после if, но и после циклов for и while. Код внутри else выполняется только в том случае, если цикл завершился естественным образом, то есть не был прерван с помощью break.

Наиболее распространённый случай использования этого — поиск элемента в цикле с прерыванием через break, если элемент найден:


# Пример 1: Список содержит нечётное число
first_odd = None
for x in [2, 3, 4, 5]:
if x % 2 == 1: # Проверяем, является ли число нечётным
first_odd = x
break # Прерываем цикл, так как элемент найден
else:
raise ValueError('No odd elements in list') # Выполнится, если цикл завершился без break

print(first_odd) # Результат: 3


Если в списке нет подходящего элемента, цикл завершается естественным образом, и выполняется блок else:


# Пример 2: Список не содержит нечётных чисел
for x in [2, 4, 6]:
if x % 2 == 1:
first_odd = x
break
else:
raise ValueError('No odd elements in list') # Исключение будет поднято

# ValueError: No odd elements in list


📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Методичка: как сделать онлайн-встречи эффективнее

Надоело ждать коллег, которые постоянно забывают о встречах, а отсутствие повестки и потерянные договоренности мешают нормально работать?

Команда МТС Линк собрала на 37 страницах полезные материалы, чек-листы и кейсы, которые помогают компаниям проводить эффективные совещания в онлайне с помощью сервиса Встречи.

Из методички узнаете:
- Как создать постоянную ссылку и подключаться на встречи в 2 клика,
- Как делать заметки и работать с файлами, не переживая за качество связи и безопасность данных.
- Как облегчает жизнь ИИ, который расшифровывает созвоны в текст и автоматически отправляет расшифровку на почту.

Еще в методичке описаны 7 способов оценки текущей эффективности ваших онлайн-встреч.

Получить гайд можно бесплатно на сайте.

Скачать

#реклама 16+
mts-link.ru

О рекламодателе

Читать полностью…

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

Запустите рекламу в телеграм-каналах с Яндекс Директом

Перфоманс-реклама теперь в телеграм-каналах ⚡

Яндекс Директ знает, как привлечь целевую аудиторию 💰👌

Попробовать

#реклама
yandex.ru

О рекламодателе

Читать полностью…

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

🔑 Использование объектов в качестве ключей словаря в Python

В 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 зарезервировано для внутренних ошибок. Если хэш-значение равно -1, интерпретатор автоматически преобразует его в -2. Это может вызывать неожиданные проблемы при сравнении или использовании объектов в качестве ключей.

📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Если вам нужно выполнить поиск в отсортированной коллекции, то бинарный поиск — это именно то, что вам нужно. Этот простой алгоритм сравнивает искомое значение с элементом в середине массива; результат определяет, какую половину нужно искать дальше.

Стандартная библиотека Python предоставляет возможность использовать бинарный поиск без его непосредственной реализации. Функция bisect_left возвращает самую левую позицию элемента в отсортированном списке, а bisect_right — самую правую.


from random import randrange
from bisect import bisect_left

n = 1000000
look_for = 555555
lst = sorted(randrange(0, n) for _ in range(n))

%timeit look_for in lst
# 69.7 ms ± 449 µs на цикл

%timeit look_for == lst[bisect_left(lst, look_for)]
# 927 ns ± 2.28 ns на цикл


Результаты демонстрируют, что использование бинарного поиска через bisect_left быстрее, чем стандартный поиск в списке с помощью оператора in.

📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Как ускорить вычисления в Python с помощью multiprocessing.Pool

Когда речь заходит о ресурсоемких задачах, которые нагружают ваш CPU, стоит обратить внимание на библиотеку multiprocessing, а именно на класс Pool. Он позволяет задействовать все доступные ядра процессора, автоматически распределяя задачи между ними.

Вот простой пример:


import math
from multiprocessing import Pool

# Генерируем список входных данных
inputs = [i ** 2 for i in range(100, 130)]

# Функция для вычислений
def f(x):
return len(str(math.factorial(x)))

# Последовательное выполнение
%timeit [f(x) for x in inputs]
# Результат: ~1.44 сек

# Параллельное выполнение
p = Pool(4) # Создаем пул из 4 процессов
%timeit p.map(f, inputs)
# Результат: ~451 мс


📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Пагинация — это стандартная задача, с которой ежедневно сталкиваются тысячи разработчиков. Если вы используете реляционную базу данных, то можно задать смещение через LIMIT, например:


SELECT *
FROM table
LIMIT 1001, 100;


Этот запрос действительно вернет 100 записей, с 1001-й по 1100-ю. Но проблема в том, что для базы данных это так же сложно, как и выборка всех первых 1001 записей. Чем дальше запрашиваемая страница, тем медленнее будет выполняться запрос.

Более оптимальным решением является использование фильтрации через WHERE, где клиент передает идентификатор последней записи текущей страницы ($last_seen_id в примере):


SELECT *
FROM table
WHERE id > $last_seen_id
ORDER BY id ASC
LIMIT 100;


Этот подход позволяет избежать сканирования всех предыдущих строк, что значительно ускоряет работу с большими объемами данных.

Если хотите разобраться подробнее, рекомендую почитать отличную статью на эту тему!

📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Прежде чем читать длиннющий релиз новой версии Python 3.14, посмотрите это видео Евгения Афонасьева, тимлида разработки Antifraud в Авито 🚀

За 12 минут он рассказал, какие фичи стоят внимания внедрения в работу, про небольшие, но приятные обновления тоже не забыл.

📺 Смотрим и обсуждаем по ссылке!

Читать полностью…

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

Почему range() в Python использует полуоткрытые интервалы?

Функция range() в Python работает с полуоткрытыми интервалами. Например, range(2, 10) задаёт числа в диапазоне [2, 10), то есть [2, 3, 4, 5, 6, 7, 8, 9]. На первый взгляд это может показаться неочевидным или асимметричным, но у такого подхода есть свои преимущества.

Почему полуоткрытые интервалы?
Полуоткрытые интервалы позволяют легко "склеивать" смежные диапазоны без риска ошибок на единицу:

- Если a = 2, b = 5, и c = 10, то [a, c) можно выразить как:


[a, c) = [a, b) + [b, c)

Это работает идеально, потому что конец одного интервала (`b`) автоматически становится началом следующего.

В случае закрытых интервалов, такая "склейка" требует дополнительной обработки:

[a, c] = [a, b] + [b+1, c]


Связь с индексацией с нуля
Индексация с нуля в Python также связана с этим принципом. Рассмотрим диапазон range(0, N):
- Этот диапазон включает ровно N элементов, что делает код более предсказуемым:

for i in range(0, N):
print(i)

Здесь i проходит значения от 0 до N-1, что логично и удобно.

Преимущества для работы с массивами
Полуоткрытые интервалы идеально подходят для работы с индексами массивов:

arr = [10, 20, 30, 40, 50]
print(arr[1:3]) # [20, 30]

Интервал [1:3) охватывает элементы с индексами 1 и 2, но не 3, что упрощает вычисления границ.

Исторический контекст
Этот подход имеет глубокие корни в компьютерной науке. Эдсгер Дейкстра, один из пионеров программирования, в 1982 году написал блестящую статью, в которой обосновал преимущества полуоткрытых интервалов. Это не просто удобство — это вопрос корректности и простоты работы с данными.

📲 Мы в MAX

👉@BookPython

Читать полностью…

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

Как использовать *args и **kwargs в python?

В видео про декораторы мы использовали *args и **kwargs для того, чтобы передать в функцию любое количество позиционных и именованных аргументов. Для того, чтобы понять как это работает, сначала познакомимся с тем, что такое распаковка.

📲 Мы в MAX

👉@BookPython

Читать полностью…
Subscribe to a channel