Привет, Хабр! В этой статье я продемонстрирую 5 трюков Python на понятных для новичков примерах, которые помогут вам писать более элегантный Python код в вашей повседневной работе.
1. Избегайте вложенных циклов с помощью product
Когда программа становится сложной, неизбежно приходится писать вложенные циклы. Однако вложенные циклы делают программы более сложными для чтения и сопровождения.
К счастью, в Python всегда можно избежать вложенных циклов с помощью встроенной функции product()
.
Например, у нас есть следующая программа, которая содержит трехуровневые вложенные циклы for
:
list_a = [1, 2020, 70]
list_b = [2, 4, 7, 2000]
list_c = [3, 70, 7]
for a in list_a:
for b in list_b:
for c in list_c:
if a + b + c == 2077:
print(a, b, c)
# 70 2000 7
Чтобы сделать код более аккуратным и чистым, мы можем использовать функцию product()
, которая находится в модуле itertools
, для оптимизации кода:
from itertools import product
list_a = [1, 2020, 70]
list_b = [2, 4, 7, 2000]
list_c = [3, 70, 7]
for a, b, c in product(list_a, list_b, list_c):
if a + b + c == 2077:
print(a, b, c)
# 70 2000 7
2. Оператор морж (:=) или способ записывать данные в переменную о котором вы не знали
Начиная с Python 3.8, появился новый синтаксис под названием «оператор морж» или walrus operator, который может присваивать значения переменным как часть более крупного выражения.
Оператор := получил свое милое название из-за глаз и бивней моржа.
Этот синтаксис очень прост для понимания. Например, если мы хотим написать следующие две строки кода Python в одной строке, как это сделать?
author = "Yang"
print(author)
# Yang
К сожалению, мы не можем напрямую поместить присвоение в функцию print(). Если мы попытаемся это сделать, возникнет ошибка типа TypeError. Но если мы используем оператор :=, то все получится!
print(author:="Yang")
# Yang
3. Самый легкий способ мерджить словари
Слияние словарей - частое действие в программировании на Python. Существует множество способов сделать это. Но все они были уродливы до версии Python 3.9.
Начиная с Python 3.9, мы наконец-то получили самый элегантный способ объединения словарей - использование операторов объединения.
cities_us = {'New York City': 'US', 'Los Angeles': 'US'}
cities_uk = {'London': 'UK', 'Birmingham': 'UK'}
cities = cities_us|cities_uk
print(cities)
# {'New York City': 'US', 'Los Angeles': 'US', 'London': 'UK', 'Birmingham': 'UK'}
Как показано в примере выше, мы можем просто использовать оператор | для слияния двух разных словарей. Более того, он также поддерживает объединение in-place:
cities_us = {'New York City': 'US', 'Los Angeles': 'US'}
cities_uk = {'London': 'UK', 'Birmingham': 'UK'}
cities_us |= cities_uk
print(cities_us)
# {'New York City': 'US', 'Los Angeles': 'US', 'London': 'UK', 'Birmingham': 'UK'}
4. Используем * для мерджа списка, кортежа и множества в одну строчку
Для того, чтобы это сделать самый элегантный способ - использование *:
A = [1, 2, 3]
B = (4, 5, 6)
C = {7, 8, 9}
L = [*A, *B, *C]
print(L)
# [1, 2, 3, 4, 5, 6, 8, 9, 7]
Звездочки можно использовать в качестве префиксов для распаковки их элементов. Но помимо распаковки, звездочки также можно использовать для деструктуризации присваиваний в Python:
a, *mid, b = [1, 2, 3, 4, 5, 6]
print(a, mid, b)
# 1 [2, 3, 4, 5] 6
Как показано выше, с помощью одной звездочки переменная mid получает элементы в середине в виде списка.
5. Используем встроенные функции в Python для написания стандартной логики
В Python есть несколько встроенных функций, которые помогают при написании некоторых стандартных логических операций.
Например, функция map()
- известная и часто используемая функция. Она получает два параметра, один из которых - функция, а другой - итератор. При выполнении функции map
функция применяется к каждому элементу в итераторе.
names = ['yAnG', 'MASk', 'thoMas', 'LISA']
names = map(str.capitalize, names)
print(list(names))
# ['Yang', 'Mask', 'Thomas', 'Lisa']
Как показано в примере выше, с помощью функции map() мы можем избежать написания цикла for для выделения заглавными буквами каждого слова в списке имен.
Другая известная функция - reduce(). Как следует из ее названия, она применяет функцию к итератору и выполняет для нее операцию reduce.
Например, в следующем примере список преобразуется в одну строку:
from functools import reduce
city = ['L', 'o', 'n', 'd', 'o', 'n', 2, 0, 2, 0]
city_to_str = reduce(lambda x, y: str(x) + str(y), city)
print(city_to_str)
# London2020
Спасибо за прочтение? Какой из хаков вы считаете самым полезным? Пишите в комментариях!
Еще больше примеров использования Python и Machine Learning в современных сервисах можно посмотреть в моем телеграм канале. Я пишу про разработку, ML, стартапы и релокацию в UK для IT специалистов.
Комментарии (15)
Vindicar
04.02.2023 11:25+121. Зачастую менее очевидно, чем циклы. Реально имеет смысл, только если циклов больше 3х, или если количество циклов заранее неизвестно. Условно, перебор всех строк из N символов в заданном алфавите.
2. У моржа очень ограниченная область применения, где он не делает хуже. Смешивать два разнородных действия в одной строке - такая себе идея.
3. Для слияния двух словарей в третий имеет смысл. Для обновления существующего словаря update() всё ещё предпочтительнее.
4. Вот этот синтаксис интересен. Не знал.
5. А вот тут лучше бы сделать акцент на том, как устроены методы в питоне. Точнее, что это функции, которые явно получают self - и практически всё. Именно поэтому "hello".captialize() и str.capitalize("hello") работает одинаково, используя один и тот же код. И в ряде случаев это поведение имеет смысл использовать - не только для строк, но и для объектов других классов. Разумеется, это работает только для методов без параметров (помимо self). В противном случае всё равно придётся использовать лямбды или functools.partial().Survtur
04.02.2023 14:444. Вот этот синтаксис интересен. Не знал.
Возможно вам понравится аналогичный синтаксис со словарями:
a = {"w": 5, "x": 6} b = {"y": 7} c = {"z": 8, **a, **b}
WASD1
04.02.2023 16:38-1Почти со всем согласен, но второй пример - это же ужас, в виде мины под будущие изменния.
a, *mid, b = [1, 2, 3, 4, 5, 6]
print(a, mid, b)
# 1 [2, 3, 4, 5] 6
igor6130
04.02.2023 13:26+6К сожалению, мы не можем напрямую поместить присвоение в функцию print().
А зачем это вообще нужно?vassabi
04.02.2023 14:19если вам действительно интересно - это сделано для if( ... ) \ while (..) и т.д.
# # как было раньше # some_filter_res = filter_func(data) if (some_filter_res): # работаем с >>>some_filter_res<<< ... # some_filter_res - пуст и не нужен # # а теперь с оператором моржа # if (some_filter_res := filter_func(data)): # работаем с >>>some_filter_res<<< ...
я думаю для while - еще нагляднее пример :)
igor6130
04.02.2023 14:51+9Я в курсе, что такое моржовый оператор. Мне было непонятно, зачем он в принте и почему автор по этому поводу так сокрушается.
fireSparrow
04.02.2023 15:44+8Подскажите, а вот на КДПВ комментарий через два слэша — это какой-то новый синтаксис в питоне?
Survtur
04.02.2023 17:00+7Есть такой способ - перед тем, как уйти на перерыв, оставить явную ошибку в том месте, на котором ты остановился. Чтобы IDE всё подчёркивало красными цветами и ничего не запускалось/не компилировалось.
Возможно это тот случай
danilovmy
05.02.2023 02:56+9Ахаха. Решил отправить свое недовольство лажовыми примерами непрямую автору статьи на medium. Оказывается, он меня уже забанил за то, что я отправлял ему свое недовольство лажовыми примерами.
This user had blocked you from following them or viewing their stories.
Странно, что, еще никто не написал, что пример в "5." это
''.join((str(bit) for bit in city))
MonsterCatz
06.02.2023 16:49Оставлю, вдруг кому тоже пригодится.
Открыл для себя недавно красивый метод вставки переменных в строку текста из списка:names = ['yAnG', 'MASk', 'thoMas', 'LISA']
print('{} {} {} {}'.format(*names))
print(('{} ' * len(names)).format(*names))
longclaps
Отнюдь не всегда:
Гнать таких знаек в шею ссаными тряпками.