5 полезных фич Python, о которых знают не все
Python – один из самых популярных и мощных ЯП, скрывающих массу полезностей и фич. Пять из них мы осветили в статье.
Даже если ты программист, перешедший с других языков, таких как C, в программирование на Python с более высоким уровнем абстракции – не стоит пугаться и отступать перед “не таким” кодом. Погнали!
List comprehensions – компактный код
Многие назвали бы lambda
,
map
и filter
"трюками" Python, которым должен научиться каждый новичок.
Принято считать, что эти функции большую часть времени, не особенно полезны,
поскольку им не хватает гибкости.
Лямбда – это метод
составления функции в одну строку для одноразового использования. Если он
вызывается несколько раз, страдает производительность. С другой стороны, map
применяет функцию ко всем элементам списка, в то время как filter
получает
подмножество элементов в наборе, удовлетворяющем пользовательскому условию.
add_func = lambda z: z ** 2 is_odd = lambda z: z%2 == 1 multiply = lambda x,y: x*y aList = list(range(10)) print(aList) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
List comprehensions – это лаконичный метод для создания списков из других списков с гибкими выражениями и условиями. Он выделяется квадратными скобками, в которых определено выражение или функция. Когда элемент удовлетворяет условию, только в этом случае действие применяется к каждому элементу списка. Метод также может обрабатывать вложенные списки продуктивнее, чем использование мапы и фильтра.
# Syntax of list comprehension [ expression(x) for x in aList if optional_condition(x) ]
print(list(map(add_func, aList))) print([x ** 2 for x in aList]) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] print(list(filter(is_odd, aList))) print([x for x in aList if x%2 == 1]) # [1, 3, 5, 7, 9] # [1, 3, 5, 7, 9]
Манипуляции со списками – циклические списки
Python поддерживает
отрицательную индексацию, где aList[-1] == aList[len(aList)-1]
. Исходя из этого,
можно получить второй последний элемент в списке – aList[-2]
и так далее.
Также можно нарезать
списки с помощью записи aList[start:end: step]
, где начальный элемент указан, а
конечный – нет. Поэтому вызов aList[2:5]
вернет [2, 3, 4]
, а вызвав aList[::
-1]
, ты сможешь переставить элементы в списке в обратном порядке – очень элегантная техника.
А еще списки могут быть распакованы в отдельные элементы или сливать элементы, которые не влезли в лимит переменных, в подсписок, используя звездочку.
a, b, c, d = aList[0:4] print(f'a = {a}, b = {b}, c = {c}, d = {d}') # a = 0, b = 1, c = 2, d = 3 a, *b, c, d = aList print(f'a = {a}, b = {b}, c = {c}, d = {d}') # a = 0, b = [1, 2, 3, 4, 5, 6, 7], c = 8, d = 9
zip, enumerate и for-loops
Функция zip
создает итератор, который агрегирует элементы из
нескольких списков. Он позволяет выполнять параллельный обход списков в цикле for
и
параллельную сортировку. Обратное действие (unzip
) совершается с помощью звездочки.
numList = [0, 1, 2] engList = ['zero', 'one', 'two'] espList = ['cero', 'uno', 'dos'] print(list(zip(numList, engList, espList))) # [(0, 'zero', 'cero'), (1, 'one', 'uno'), (2, 'two', 'dos')] for num, eng, esp in zip(numList, engList, espList): print(f'{num} is {eng} in English and {esp} in Spanish.') # 0 is zero in English and cero in Spanish. # 1 is one in English and uno in Spanish. # 2 is two in English and dos in Spanish.
Eng = list(zip(engList, espList, numList)) Eng.sort() # sort by engList a, b, c = zip(*Eng) print(a) print(b) print(c) # ('one', 'two', 'zero') # ('uno', 'dos', 'cero') # (1, 2, 0)
enumerate
может
показаться немного пугающим, но данную функцию удобно
применять во многих ситуациях. Наиболее популярный вариант – автоматический
счетчик для цикла for
: больше нет
необходимости создавать и инициализировать переменную счетчика с помощью counter = 0
и counter
+= 1
. enumerate
и zip
– это два самых мощных инструмента при построении
цикла for
.
upperCase = ['A', 'B', 'C', 'D', 'E', 'F'] lowerCase = ['a', 'b', 'c', 'd', 'e', 'f'] for i, (upper, lower) in enumerate(zip(upperCase, lowerCase), 1): print(f'{i}: {upper} and {lower}.') # 1: A and a. # 2: B and b. # 3: C and c. # 4: D and d. # 5: E and e. # 6: F and f.
Генератор – эффективность использования памяти
Генераторы используются, когда нужно вычислить большой набор результатов, но необходимо избежать одновременного выделения памяти под все результаты. Другими словами, они генерируют значения на лету и не хранят предыдущие значения в памяти, поэтому их можно итерировать только раз.
Они часто используются
при чтении больших файлов или создании бесконечной последовательности при
помощи ключевого слова yield
.
def gen(n): # an infinite sequence generator that generates integers >= n while True: yield n n += 1 G = gen(3) # starts at 3 print(next(G)) # 3 print(next(G)) # 4 print(next(G)) # 5 print(next(G)) # 6
Виртуальная среда – изоляция
Самая интересная и увлекательная штука из подборки.
Приложения Python часто используют множество пакетов от различных разработчиков со сложными зависимостями. Разные приложения создаются с использованием определенных наборов библиотек, в которых выходные данные не могут быть использованы другими версиями библиотеки. Не существует единой установки, которая удовлетворяла бы требованиям всех приложений.
conda create -n venv pip python=3.7 # select python version source activate venv ... source deactivate
Поэтому крайне важно создать отдельные автономные виртуальные среды venv для каждого приложения, что и можно сделать с помощью pip или conda.