image

Те, кто работает с Python, знают, что этот язык хорош благодаря своей обширной экосистеме. Можно даже сказать, что язык программирования не выделялся бы ничем особенным, если бы не его замечательные пакеты, которые добавляют новые функции к основным.

В качестве примера можно привести NumPy. Инструменты работы с матрицами хороши и в базовом Python, но использование NumPy улучшает все во много раз. Кроме того, у этого языка есть несколько крутых возможностей, которые делают его еще более функциональным. Используя эти возможности, вы можете уменьшить количество зависимостей, освободить время и упростить сам процесс разработки. Давайте посмотрим, что это за возможности.

Кстати, свои советы по некоторым функциям добавил Алексей Некрасов — лидер направления Python в МТС, программный директор направления Python в Skillbox. Чтобы было понятно, где перевод, а где — комментарии, последние мы выделим текстом.

№1 lambda


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

Она позволяет вводить определения в глобальном масштабе, а также использовать functional-like синтаксис и методологию, причем на языке, у которого все еще есть структура классов.

Все это позволяет сэкономить время в ходе написания программы, сохранить ресурсы и сделать код более лаконичным. Более того, lambda дает возможность использовать такие методы, как apply() для быстрого применения выражений ко всем подмножествам данных. Для дата-сайентиста, да и не только для представителей этой профессии, подобные возможности крайне полезны.

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

mean = lambda x : sum(x) / len(x)

Теперь мы можем осуществить вызов, как и в случае с любым другим методом в Python:

x = [5, 10, 15, 20]
print(mean(x))

Комментарий Алексея:

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

Правильно:

def f (x): return 2 * x

Неправильно:

f = lambda x: 2 * x

Если длина lambda выражения больше 40 символов, то скорее всего вы засунули в одну строчку кода слишком много логики и она стала нечитабельна. Так делать не стоит, лучше вынести в отдельную функцию.

№2: Shutil


Модуль Shutil — один из наиболее недооцененных инструментов в арсенале Python. Он включен в стандартную библиотеку, и может быть импортирован так же, как и любой другой модуль в языке:

import shutil

Что же делает shutil? На самом деле, это интерфейс высокого уровня для языка программирования Python, в отношении файловой системы вашей ОС. Эти вызовы часто выполняются с использованием модуля os, об shutil не стоит забывать. Вероятно, вам приходилось перемещать файл из каталога в каталог при помощи скрипта, проделав для этого массу утомительной работы, верно?

Shutil решает эти классические проблемы с файлами и таблицами размещения (allocation tables) при помощи высокоуровневого решения. Это — ключ для экономии времени и ускорению операций с файлами. Вот несколько примеров высокоуровневых вызовов, которые предоставляет shutil.

import shutil
shutil.copyfile('mydatabase.db', 'archive.db')
shutil.move('/src/High.py', '/packages/High')

№3: glob


Возможно, glob и не такой классный, как shutil, плюс он и рядом не стоял с lambda в плане полезности. Но он незаменим в некоторых случаях. Этот модуль используется для поиска директорий для wildcards. Это означает, что его можно использовать для агрегирования данных о файлах на вашем ПК и их расширениях. Импортируется модуль без проблем:

import glob

Я не уверен, есть ли у этого модуля еще функции, но glob() — то, что нужно для выполнения поиска файлов. В ходе поиска используется синтаксис Unix, т.е. т.е. *, / и т. д.

glob.glob('*.ipynb')

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

№4: argparse


Этот модуль предоставляет надежный и глубокий метод анализа аргументов командной строки. Многие инструменты разработки используют эту концепцию, работать со всем этим можно при помощи командной строки Unix. Отличный пример — Python Gunicorn, обрабатывающий переданные аргументы командной строки. Для начала работы с модулем его нужно импортировать.

import argparse

Затем, чтобы получить возможность работать с ним, строим новый тип, это будет парсер аргументов:

parser = argparse.ArgumentParser(prog = 'top',
description = 'Show top lines from the file')

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

parser.add_argument('-l', '--lines', type=int, default=10)

Здесь добавлено несколько аргументов ключевого слова, один из которых предоставит тип данных, который передается для этого аргумента, а другой — значение по умолчанию, когда файл вызывается без этого аргумента. Теперь мы можем получить аргументы, вызвав функцию parse_args () для нашего нового типа парсера аргументов:

args = parser.parse_args()

Теперь мы можем вызвать этот файл Python для компиляции, а также легко предоставить необходимые параметры из Bash.

python top.py --lines=5 examplefile.txt

Излишне говорить, что это определенно может пригодиться. Я часто использовал этот модуль при работе с Crontab. Он может запускать скрипты с определенными временными метками Unix. Кроме того, этот сценарий также можно использовать для супервизоров, которые запускают команды Bash без участия пользователя в качестве worker.

№5: import re


Еще один крайне недооцененный модуль. Модуль re используется для синтаксического анализа строк с помощью регулярных выражений и предоставляет больше возможностей для работы со строками в Python. Сколько раз вы сталкивались с принятием алгоритмических решений на основе функций, которые есть в строковом классе, например str.split ()? Но хватит это терпеть! Ведь регулярные выражения намного проще и их намного проще использовать!

import re

Модуль re, в отличие от некоторых других в этом списке, предоставляет не одну, а множество крайне полезных функций. Они особенно актуальны для работы с большими объемами данных, что важно для дата-саентистов. Вот два примера, с которых стоит начать, — это функции sub () и findall ().

import re
re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
'cat in the hat'

Комментарий Алексея:

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

  • re.compile. Использовать re.compile (или его аналог в других языках) для любых более менее сложных и длинных regex.
  • Избегать многократного вызова re.compile на один и тот же regex.
  • Писать подробные регулярные выражения используя дополнительный аргумент re.VERBOSE. При re.compile использовать флаг re.VERBOSE (или его аналог в других языках) писать regex в несколько строк с комментариями о том что происходит. Смотри документацию по ссылкам тут и тут.

Пример:
компактный вид

pattern = '^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$'
re.search(pattern, 'MDLV')

Подробный вид

pattern = '''
    ^                   # beginning of string
    M{0,3}              # thousands - 0 to 3 Ms
    (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 Cs),
                        #            or 500-800 (D, followed by 0 to 3 Cs)
    (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 Xs),
                        #        or 50-80 (L, followed by 0 to 3 Xs)
    (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 Is),
                        #        or 5-8 (V, followed by 0 to 3 Is)
    $                   # end of string
    '''
re.search(pattern, 'M', re.VERBOSE)

  • Использовать python raw string для записи regex.
  • Named capture group для всех capture group, если их больше чем одна (?P...). (даже если одна capture, тоже лучше использовать)
    regex101.com отличный сайт для дебага и проверки regex

№6: Math


Это не величайший модуль в истории, но часто он полезен. Математический модуль дает доступ ко всему, от sin и cos до логарифмов. Все это крайне важно при работе с алгоритмами.

import math

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

import math
math.log(1024, 2)

№7: Statistics


Еще один модуль, который крайне полезен для статистических подсчетов. Он дает доступ к базовой статистике — не такой глубокой, как в случае SCiPy, но и ее может быть достаточно для анализа данных. Alias этого модуля — st, в некоторых случаях — stc или sts. Но, внимание — не scs, это уже alias для Scipy.stats.

import statistics as st

Этот модуль предоставляет множество полезных функций, на которые стоит обратить внимание! Самое замечательное в этом пакете то, здесь нет никаких зависимостей. Давайте оценим некоторые основные статистические операции общего назначения:

import statistics as st
st.mean(data)
st.median(data)
 
st.variance(data)

№8: urllib


Если многие другие модули из этого списка не очень известны, то urlib — исключение. Давайте импортируем его!

import urllib

Вместо него можно использовать Flask, поскольку он более функционален. Но для большинства базовых функций хватает и возможностей стандартной библиотеки, которая дает возможность не беспокоиться о зависимостях. Конечно, если нужны дополнительные возможности — то в этом случае стоит обратить внимание уже на что-то другое. Но если речь об HTTP-запросе, то urlib сделает то, что нужно.

from urllib.request import urlopen
 
data = null
with urlopen('http://example_url/') as response: data = response

Модуль urlib — то, что я крайне рекомендую изучить дополнительно.

№9: datetime


Еще один отличный пример инструмента, который довольно часто встречается в научных вычислениях, — это тип «дата и время». Очень часто у данных есть отметки времени. Иногда они даже являются прогностической функцией, используемой для обучения модели. Этот модуль часто используется с алиасом dt:

import datetime as dt

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

import datetime as dt
now = dt.date.today()
print(now.year)
print(now.month)

№10: zlib


Последний участник этого списка — модуль zlib. Это универсальное решение для сжатия данных с использованием языка программирования Python. Модуль крайне полезен при работе с пакетами.

import zlib

Наиболее важные функции здесь — compress() and decompress().

h = " Hello, it is me, you're friend Emmett!"print(len(h))
t = zlib.compress(h)
print(len(t))
z = decompress(t)
print(len(z))

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