Сохранение документации функции при декорировании
У декораторов существует ряд проблем, одна из которых заключается в том, что, после оборачивания функции в декоратор, на выходе мы не можем получить информацию атрибутов
Вместо значений данных атрибутов исходной функции мы будем получать значения функции обертки.
Для решения этой проблемы можно воспользоваться декоратором
#декораторы #wraps
У декораторов существует ряд проблем, одна из которых заключается в том, что, после оборачивания функции в декоратор, на выходе мы не можем получить информацию атрибутов
__name__
и __doc__
, нужные для документации функции. Вместо значений данных атрибутов исходной функции мы будем получать значения функции обертки.
Для решения этой проблемы можно воспользоваться декоратором
functools.wraps
, применяя его к обертке нашего декоратора. В результате имя и сигнатура функции, передаваемой в декоратор, будут копироваться в обертку.#декораторы #wraps
3 трюка с itertools
Начнем с функции
Для того, чтобы составить комбинацию с повторениями, используют функцию
Ну и в заключение, рассмотрим функцию
#itertools
Начнем с функции
combinations
: она позволяет составлять комбинации элементов из итерируемых объектов без повторений. Первый аргумент это сам объект, а второй — длина комбинации.Для того, чтобы составить комбинацию с повторениями, используют функцию
combinations_with_replacement
. Делает она абсолютно все то же самое что и предыдущая, с одним исключением – теперь в комбинации могут быть повторы.Ну и в заключение, рассмотрим функцию
compress
, применяющую "маску" из второго аргумента функции к первому. То есть, если в маске на этом месте стоит единица, то в исходном массиве элемент остается нетронутым, и наоборот.#itertools
Определение литеральных типов
Когда нам может понадобится определить из полученной строки литеральный тип (строки, числа, списки, кортежи, словари, логические значения и None), мы можем воспользоваться функцией
Данная функция поможет безопасно определить литеральный тип, а в случае если был передан не литерал, то выбросит исключение. Это можно использовать для оценки выражений из внешних источников при парсинге файлов, либо пользовательского ввода.
#ast #literal_eval
Когда нам может понадобится определить из полученной строки литеральный тип (строки, числа, списки, кортежи, словари, логические значения и None), мы можем воспользоваться функцией
literal_eval()
из модуля ast
.Данная функция поможет безопасно определить литеральный тип, а в случае если был передан не литерал, то выбросит исключение. Это можно использовать для оценки выражений из внешних источников при парсинге файлов, либо пользовательского ввода.
#ast #literal_eval
Генераторы
Функции-генераторы выглядят как и обычные, но вместо
Вызов подобной функции вернёт не значение, а объект генератора. Далее из этого объекта можно получать значения, например, с помощью функции
Если генератору больше нечего возвращать, то будет вызвано исключение
#генераторы
Функции-генераторы выглядят как и обычные, но вместо
return
содержат выражения с ключевым словом yield
для последовательного генерирования значений.Вызов подобной функции вернёт не значение, а объект генератора. Далее из этого объекта можно получать значения, например, с помощью функции
next
или циклом for
.Если генератору больше нечего возвращать, то будет вызвано исключение
StopIteration
. В целом, генератор — это особый, более изящный случай итератора.#генераторы
Корутины
Некой противоположностью генераторов являются корутины. Для примера напишем функцию, которая будет в бесконечном цикле подставлять значение и выводить строку.
Обратите внимание на то, как было использовано ключевое слово
Функция работает так: при отправке значения через метод
#генераторы #корутины
Некой противоположностью генераторов являются корутины. Для примера напишем функцию, которая будет в бесконечном цикле подставлять значение и выводить строку.
Обратите внимание на то, как было использовано ключевое слово
yield
. При таком написании создаётся не генератор, а корутина, что позволяет не просто генерировать значения, но и принимать их.Функция работает так: при отправке значения через метод
send
локальная переменная name
принимает его, а далее значение подставляется в строку и выводится на экран.#генераторы #корутины
Хэширование
Для создания хэш-значений в python существует удобный модуль
Использование очень простое, в модуле существует ряд конструкторов, соответствующих названиям хэш-функций. В конструктор мы можем передать байт-строку, хэш которой мы хотим получить, на выходе мы получим объект хэша. Объект хэша мы можем обновить методом
#hash #hashlib
Для создания хэш-значений в python существует удобный модуль
hashlib
, реализующий общий интерфейс для ряда популярных хэш функций и также может использовать функции доступные в системе, предоставляемые с установленным OpenSSL.Использование очень простое, в модуле существует ряд конструкторов, соответствующих названиям хэш-функций. В конструктор мы можем передать байт-строку, хэш которой мы хотим получить, на выходе мы получим объект хэша. Объект хэша мы можем обновить методом
update
, сконкатенировав тем самым строки, а также можем можем вывести полученное значение с помощью методов digest
и hexdigest
. Первый возвращает байт-строку, второй - в шестнадцатеричном формате.#hash #hashlib
Нижнее подчеркивание
В Python имя переменной может состоять из одного подчеркивания. Хотя такое имя не достаточно описательно и не должно использоваться, есть по крайней мере три случая, когда
Первое,
Второе, интерактивный режим использует
Третье, документация модуля
#тонкости
В Python имя переменной может состоять из одного подчеркивания. Хотя такое имя не достаточно описательно и не должно использоваться, есть по крайней мере три случая, когда
_
имеет общепринятый смысл.Первое,
_
используется, когда вам нужно придумать имена для значений, которые вам не нужны — например, в циклах for
.Второе, интерактивный режим использует
_
для хранения результата последнего выполненного выражения.Третье, документация модуля
gettext
рекомендует псевдоним _()
для функции gettext()
, чтобы минимизировать загромождение вашего кода.#тонкости
Ключевое слово global
Изначально мы не можем изменять значение переменной в другой области видимости, но мы можем это сделать, переопределив область видимости на глобальную, с помощью ключевого слова
Мы даже можем определить новую глобальную переменную внутри функции, но не нужно этим злоупотреблять, т.к. это будет засорять глобальную область и приводить к нежелательным ошибкам
#переменные #global
Изначально мы не можем изменять значение переменной в другой области видимости, но мы можем это сделать, переопределив область видимости на глобальную, с помощью ключевого слова
global
.Мы даже можем определить новую глобальную переменную внутри функции, но не нужно этим злоупотреблять, т.к. это будет засорять глобальную область и приводить к нежелательным ошибкам
#переменные #global
Ключевое слово nonlocal
Похожее по функционалу на global, ключевое слово
Поведение
Основное различие с
#переменные #nonlocal
Похожее по функционалу на global, ключевое слово
nonlocal
позволяет обращаться к переменным из нелокальной области видимости.Поведение
nonlocal
заключается в том, что интерпретатор ищет переменную в ближайшей области видимости.Основное различие с
global
в том, что с помощью nonlocal
нельзя получить переменные из глобальной области видимости.#переменные #nonlocal
Работаем со временем без головной боли
При работе со временем и датами у встроенных модулей есть несколько неприятных моментов:
— Их слишком много:
— В них слишком много типов:
И вот на днях я наткнулся на пакет arrow, который их решает. Во-первых, там есть все необходимое. Во-вторых, все объекты имеют один и тот же тип
Большой плюс в том, что пакет совместим с основными встроенными типами. Например, выше я преобразовал
Еще из приятных бонусов: там есть функция
#время #arrow
При работе со временем и датами у встроенных модулей есть несколько неприятных моментов:
— Их слишком много:
datetime
, time
, calendar
, dateutil
, pytz
и другие; — В них слишком много типов:
date
, time
, datetime
, tzinfo
, timedelta
, relativedelta
и т. д. И вот на днях я наткнулся на пакет arrow, который их решает. Во-первых, там есть все необходимое. Во-вторых, все объекты имеют один и тот же тип
Arrow
. Большой плюс в том, что пакет совместим с основными встроенными типами. Например, выше я преобразовал
datetime
в Arrow
и обратно. Еще из приятных бонусов: там есть функция
humanize
, которая конвертирует время в читаемый текст. #время #arrow
Аргументы и параметры командной строки
Для обработки передаваемых аргументов и создания удобный интерфейс командной строки в python есть отличный модуль
Для начала нам нужно создать объект парсера
Первым параметром
После добавления всех аргументов, нам нужно их спарсить с помощью метода
#argparse
Для обработки передаваемых аргументов и создания удобный интерфейс командной строки в python есть отличный модуль
argparse
.Для начала нам нужно создать объект парсера
ArgumentParser
, в который мы уже сможем добавить аргументы с нужными параметрами с помощью метода add_argument
.Первым параметром
add_argument
принимает либо имя обязательного позиционного аргумента, либо список опционального аргумента (опциональный аргумент идентифицируется через -
). Также у add_argument
есть множество необязательных опциональных параметров для работы с передаваемым значением аргумента, о них можете почитать в данной статье.После добавления всех аргументов, нам нужно их спарсить с помощью метода
parse_args
, на выходе мы получим объект со всеми содержащимися аргументами.#argparse
Методы у словарей
В этом посте поговорим про 3 простых метода у словарей, которые позволяет получить элементы в разном виде.
С помощью метода
А метод
#словари
В этом посте поговорим про 3 простых метода у словарей, которые позволяет получить элементы в разном виде.
С помощью метода
dict.keys()
можно получить ключи словаря в виде списка, dict.values()
— то же самое, но со значениями.А метод
dict.items()
возвращает список из кортежей, которые содержат ключи и соответствующие значения.#словари
3 интересных функции в random
Этот пост более для тех, у кого есть соответствующий бэкграунд и кто хочет знать про
Кстати, можете посмотреть на графиках результаты вызова этих функций по 100к раз тут, тут и тут.
#random
Этот пост более для тех, у кого есть соответствующий бэкграунд и кто хочет знать про
random
больше среднего.betavariate()
— используется для получения случайного числа с плавающей запятой от 0 до 1 на основе бета-распределения (применяется для статистических расчетов).gauss()
— генерирует случайное число с плавающей запятой на основе распределения Гаусса (используется в теории вероятности).paretovariate()
— возвращает случайное число с плавающей запятой на основе распределения Парето (используется в теории вероятности).Кстати, можете посмотреть на графиках результаты вызова этих функций по 100к раз тут, тут и тут.
#random
Создаем бесконечный итератор
Функция
Фишка заключается в том, что когда элементы последовательности заканчиваются, итерация начинается вновь с первого элемента.
Но если вы проходитесь циклом по такому итератору, то важно предусмотреть выход из цикла, иначе он станет бесконечным (как у нас в первом случае на картинке).
Мы также можем воспользоваться
#itertools
Функция
cycle()
из itertools
принимает на вход итерируемый объект и создает бесконечный итератор, циклически возвращающий элементы данного объекта.Фишка заключается в том, что когда элементы последовательности заканчиваются, итерация начинается вновь с первого элемента.
Но если вы проходитесь циклом по такому итератору, то важно предусмотреть выход из цикла, иначе он станет бесконечным (как у нас в первом случае на картинке).
Мы также можем воспользоваться
islice()
, который вернет итератор по подмножеству переданного объекта.#itertools
Получаем список переменных
Функция
С помощью похожей функции
Еще обратите внимание на результат второй функции: там много разных переменных, которые мы явно не объявляли — про некоторые из них скоро расскажем.
#переменные
Функция
locals()
возвращает словарь переменных из текущего пространства имён. Ключи словаря — названия переменных, а значения — это их значения.С помощью похожей функции
globals()
можно получить все переменные конкретного модуля в таком же виде.Еще обратите внимание на результат второй функции: там много разных переменных, которые мы явно не объявляли — про некоторые из них скоро расскажем.
#переменные
Специальная переменная __name__
Когда интерпретатор Python читает файл, то сначала он устанавливает несколько специальных переменных (пример). Одной из таких переменных является
Если скрипт был запущен напрямую, то в переменную присваивается значение
Типичный пример использования такой переменной — создание точки входа в программу. Про это уже был ранее пост.
Вообще атрибут
#переменные
Когда интерпретатор Python читает файл, то сначала он устанавливает несколько специальных переменных (пример). Одной из таких переменных является
__name__
.Если скрипт был запущен напрямую, то в переменную присваивается значение
__main__
, в случае импорта — название модуля.Типичный пример использования такой переменной — создание точки входа в программу. Про это уже был ранее пост.
Вообще атрибут
__name__
по умолчанию также ставится всем классам и функциям.#переменные
Копируем объекты
При присваивании переменной значения другой переменной, как правило, новый объект не создается, а копируется ссылка уже на существующий.
Если использовать функцию
В случае с
#copy
При присваивании переменной значения другой переменной, как правило, новый объект не создается, а копируется ссылка уже на существующий.
Если использовать функцию
copy
из стандартной библиотеки, то новый объект будет создан, но его ссылки на другие объекты останутся такими же.В случае с
deepcopy
произойдет рекурсивное копирование. Например, при таком копировании списка все его элементы также скопируются как новые объекты.#copy
Валидаторы данных
Как правило, разработчики пишут регулярные выражения для обработки специфических строк. Но для таких данных как, почта или ссылка, изобретать велосипед не нужно.
Модуль
Помимо этого,
#validators
Как правило, разработчики пишут регулярные выражения для обработки специфических строк. Но для таких данных как, почта или ссылка, изобретать велосипед не нужно.
Модуль
validators
позволяет использовать уже готовые валидаторы для самых распространенных задач. В примере можете как раз увидеть валидацию почты и ссылок.Помимо этого,
validators
позволяет также работать с ipv4, ipv6, mac адресами и многим другим. В итоге, имеем лаконичный и простой модуль с хорошим функционалом.#validators
Интересная пасхалка
Модуль
Но будет вызвано исключение, которое говорит "not a chance", что означает "ни единого шанса". Однако есть ещё один интересный момент, а именно — исходный код этого модуля.
Оказывается, интерпретатор CPython сначала запускает файл
#пасхалки
Модуль
__future__
позволяет подключать функционал из будущих версий языка. Например, можно попробовать импортировать фигурные скобки как в си-подобных языках.Но будет вызвано исключение, которое говорит "not a chance", что означает "ни единого шанса". Однако есть ещё один интересный момент, а именно — исходный код этого модуля.
Оказывается, интерпретатор CPython сначала запускает файл
future.c
, когда встречается импорт этого модуля. А само это исключение реализовано на этой строчке.#пасхалки