Библиотека Python разработчика | Книги по питону
19.2K subscribers
1.05K photos
391 videos
82 files
998 links
Полезные материалы для питониста по Фреймворкам Django, Flask, FastAPI, Pyramid, Tornado и др.

По всем вопросам @evgenycarter

РКН clck.ru/3Ko7Hq
Download Telegram
Очередь с приоритетами - это структура данных, которая поддерживает две операции: добавление элемента и извлечение минимального элемента среди всех ранее добавленных.

Одна из самых распространённых реализаций очереди с приоритетами - бинарная куча (binary heap). Это полное бинарное дерево, обладающее следующим свойством: ключ, хранящийся в каждом узле, меньше или равен (≤) ключам в дочерних узлах.
Минимальный элемент из всех находится в корне дерева.


1

3 7

5 4 9 8

15 16 17 18 19


В бинарной куче операции вставки и извлечения минимального элемента выполняются за O(log n).


Хранение бинарной кучи в памяти

Полное бинарное дерево обычно хранится в массиве, где:

* левый потомок элемента x[i] находится по индексу 2*i + 1,
* правый потомок - по индексу 2*i + 2.

Пример массива для дерева выше:


[1, 3, 7, 5, 4, 9, 8, 15, 16, 17, 18, 19]



Работа с кучей в Python

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

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


from heapq import *

# Создаём список
heap = [3, 2, 1]

# Преобразуем список в кучу
heapify(heap)
print(heap) # [1, 2, 3]

# Добавляем элемент в кучу
heappush(heap, 0)
print(heap) # [0, 1, 3, 2]

# Извлекаем минимальный элемент
print(heappop(heap)) # 0

# Куча после извлечения
print(heap) # [1, 2, 3]


👉@BookPython
👍1
Вы можете передавать аргументы в пользовательский метакласс прямо из определения класса.
Синтаксис класса поддерживает именованные аргументы:


class Klass(Parent, arg='arg')


Ключевое слово metaclass зарезервировано для указания метакласса, но остальные аргументы можно использовать свободно.

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


class FilterMeta(type):
def __new__(mcs, name, bases, namespace, remove=None, **kwargs):
if remove is not None and remove in namespace:
del namespace[remove]

return super().__new__(mcs, name, bases, namespace)


class A(metaclass=FilterMeta, remove='half'):
def half(x):
return x // 2

half_of_4 = half(4)
half_of_100 = half(100)


a = A()
print(a.half_of_4) # 2
print(a.half_of_100) # 50
a.half # AttributeError


В этом примере метод half удаляется из класса A во время его создания, поэтому попытка обратиться к a.half вызывает AttributeError.

👉@BookPython
👍1
Стандартный модуль json имеет интерфейс командной строки, который может быть полезен для форматирования JSON с помощью одного только Python. Этот модуль называется json.tool и используется следующим образом:


$ echo '{"a": [], "b": "c"}' | python -m json.tool
{
"a": [],
"b": "c"
}


👉@BookPython
👍3
Генератор можно остановить. Ты можешь явно вызвать g.close(), но обычно это делает сборщик мусора. Когда вызывается close, в точке, где выполнение генератора было приостановлено, выбрасывается исключение GeneratorExit:


def gen():
try:
yield 1
yield 2
finally:
print('END')


g = gen()
print(next(g)) # выведет '1'
g.close() # выведет 'END'


Обрати внимание на три момента:


1. Нельзя использовать yield при обработке GeneratorExit

Если в блоке finally попытаться сделать yield, возникнет ошибка RuntimeError:


def gen():
try:
yield 1
finally:
yield 3 # ошибка!


g = gen()
next(g)
g.close() # RuntimeError



2. Исключение не выбрасывается, если генератор ещё не запускался

В этом случае генератор просто переходит в состояние остановлен, но finally не выполняется:


def gen():
try:
yield 1
finally:
print('END')


g = gen()
g.close() # ничего не выводит
print(list(g)) # выведет '[]'



3. close() ничего не делает, если генератор уже завершён

Если генератор полностью отработал, close() не вызывает finally повторно и просто игнорируется:


def gen():
try:
yield 1
yield 2
finally:
print('END')


g = gen()
print(list(g)) # ['1', '2']
print('Closing now')
g.close()

# Вывод:
# END
# [1, 2]
# Closing now


👉@BookPython
👍3
Модуль functools для манипуляций с функциями

Модуль functools в Python предоставляет инструменты для работы с функциями, позволяя выполнять различные манипуляции с ними. Вот некоторые из наиболее важных функций и возможностей, которые предоставляет functools:

1. functools.partial: Позволяет зафиксировать некоторые аргументы функции и создать новую функцию с предопределенными значениями.


from functools import partial

def multiply(x, y):
return x * y

double = partial(multiply, 2)
print(double(5)) # Вывод: 10


2. functools.reduce: Применяет функцию к паре элементов в последовательности, сокращая ее до одного значения. Обычно используется для аккумуляции значений.


from functools import reduce

numbers = [1, 2, 3, 4]
product = reduce(lambda x, y: x * y, numbers)
print(product) # Вывод: 24


3. functools.lru_cache: Кэширует результаты вызовов функции, чтобы ускорить повторные вызовы с теми же аргументами. Полезно для функций с дорогими вычислениями.


from functools import lru_cache

@lru_cache(maxsize=None)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(10)) # Вывод: 55


4. functools.wraps: Декоратор, который сохраняет метаданные оригинальной функции (такие как имя и документация) при создании декоратора.


from functools import wraps

def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("Что-то делаем перед вызовом функции")
return func(*args, **kwargs)
return wrapper

@my_decorator
def say_hello():
"""Выводит приветствие."""
print("Привет!")

print(say_hello.__name__) # Вывод: say_hello
print(say_hello.__doc__) # Вывод: Выводит приветствие.


5. functools.total_ordering: Упрощает реализацию всех методов сравнения для класса, определяя только несколько из них.


from functools import total_ordering

@total_ordering
class Point:
def __init__(self, x, y):
self.x = x
self.y = y

def __eq__(self, other):
return (self.x, self.y) == (other.x, other.y)

def __lt__(self, other):
return (self.x, self.y) < (other.x, other.y)

p1 = Point(1, 2)
p2 = Point(3, 4)
print(p1 < p2) # Вывод: True
print(p1 <= p2) # Вывод: True


Эти функции и декораторы делают functools мощным инструментом для функционального программирования в Python.

Мы в MAX

👉@BookPython
👍4
Когда вы пишете собственный метод __repr__ для какого-то объекта, обычно нужно включать представление его атрибутов. Для этого при форматировании следует вызывать repr() для объектов, так как по умолчанию вызывается str().

Это делается с помощью нотации !r:


class Pair:
def __init__(self, left, right):
self.left = left
self.right = right

def __repr__(self):
class_name = type(self).__name__
return f'{class_name}({self.left!r}, {self.right!r})'


Мы в MAX

👉@BookPython
👍3
Что такое Pickling и Unpickling?

В Python pickling и unpickling — это процессы сериализации и десериализации объектов, соответственно, с использованием модуля pickle.

- Pickling — это процесс преобразования объекта Python (например, словаря, списка, класса и т.д.) в байтовую последовательность (или поток байтов), которая может быть сохранена в файл или передана по сети. Этот процесс позволяет сохранить состояние объекта для дальнейшего использования.

- Unpickling — это обратный процесс, при котором байтовая последовательность преобразуется обратно в объект Python.

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

1. Pickling (сериализация):


import pickle

# Создаем объект
data = {'name': 'Alice', 'age': 25, 'city': 'New York'}

# Сохраняем объект в файл
with open('data.pickle', 'wb') as f:
pickle.dump(data, f)


2. Unpickling (десериализация):


import pickle

# Читаем объект из файла
with open('data.pickle', 'rb') as f:
loaded_data = pickle.load(f)

print(loaded_data)


Когда это может быть полезно?
- Сохранение промежуточных данных в файл для повторного использования.
- Передача сложных объектов между разными программами или системами.
- Сохранение состояния приложения.

Однако, нужно быть осторожным с unpickling, так как загрузка непроверенных данных может привести к выполнению вредоносного кода.

Мы в MAX

👉@BookPython
👍2
PikaScript

Ультралегкий интерпретатор Python, работающий всего с 4 КБ оперативной памяти, с нулевыми зависимостями. Он готов к использованию из коробки, не требует конфигурации и легко расширяется с помощью языка C. Похожие проекты: MicroPython, JerryScript.

Все это позволяет вам программировать на языке Python даже для самых маломощных микроконтроллеров семейства STM32

https://github.com/pikasTech/PikaPython

Мы в MAX

👉@BookPython
👍4
Сравнение производительности dict() и {} в Python

Какое-то время назад, во время разбора кода, мы обсудили выбор dict() вместо {} в новом коде на Python. Коллега утверждал, что dict() более читаем и чётче выражает предназначение кода, поэтому следует предпочесть его. Меня это не убедило, но в тот момент контраргументов не нашлось, поэтому я воздержался.

Это заставило меня задуматься: в чём разница между типом dict и литеральным выражением {}?


https://habr.com/ru/articles/788440/

original https://madebyme.today/blog/python-dict-vs-curly-brackets/

Мы в MAX

👉@BookPython
👍3