Comments 22
К счастью, в Python всегда можно избежать вложенных циклов с помощью встроенной функции
product()
Отнюдь не всегда:
for a in range(3):
for b in range(a):
for c in range(a + b):
print(a, b, c)
Гнать таких знаек в шею ссаными тряпками.
1. Зачастую менее очевидно, чем циклы. Реально имеет смысл, только если циклов больше 3х, или если количество циклов заранее неизвестно. Условно, перебор всех строк из N символов в заданном алфавите.
2. У моржа очень ограниченная область применения, где он не делает хуже. Смешивать два разнородных действия в одной строке - такая себе идея.
3. Для слияния двух словарей в третий имеет смысл. Для обновления существующего словаря update() всё ещё предпочтительнее.
4. Вот этот синтаксис интересен. Не знал.
5. А вот тут лучше бы сделать акцент на том, как устроены методы в питоне. Точнее, что это функции, которые явно получают self - и практически всё. Именно поэтому "hello".captialize() и str.capitalize("hello") работает одинаково, используя один и тот же код. И в ряде случаев это поведение имеет смысл использовать - не только для строк, но и для объектов других классов. Разумеется, это работает только для методов без параметров (помимо self). В противном случае всё равно придётся использовать лямбды или functools.partial().
4. Вот этот синтаксис интересен. Не знал.
Возможно вам понравится аналогичный синтаксис со словарями:
a = {"w": 5, "x": 6}
b = {"y": 7}
c = {"z": 8, **a, **b}
Почти со всем согласен, но второй пример - это же ужас, в виде мины под будущие изменния.
a, *mid, b = [1, 2, 3, 4, 5, 6]
print(a, mid, b)
# 1 [2, 3, 4, 5] 6
"hello".captialize() и str.capitalize("hello") работает одинаково, используя один и тот же код.
Но второе может перестать работать, если вместо строки у вас что-то совместимое со строкой. Для строк может не так критично, а в других случаях - может выстрелить. В питоне все таки утиная типизация.
К сожалению, мы не можем напрямую поместить присвоение в функцию print().
А зачем это вообще нужно?
если вам действительно интересно - это сделано для 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 - еще нагляднее пример :)
Ахаха. Решил отправить свое недовольство лажовыми примерами непрямую автору статьи на medium. Оказывается, он меня уже забанил за то, что я отправлял ему свое недовольство лажовыми примерами.
This user had blocked you from following them or viewing their stories.
Странно, что, еще никто не написал, что пример в "5." это ''.join((str(bit) for bit in city))
Оставлю, вдруг кому тоже пригодится.
Открыл для себя недавно красивый метод вставки переменных в строку текста из списка:
names = ['yAnG', 'MASk', 'thoMas', 'LISA']
print('{} {} {} {}'.format(*names))
print(('{} ' * len(names)).format(*names))
/*DISCLAIMER: я не python разработчик, но некоторые вещи, достаточно комплексные, в том числе, приходилось и разбирать и дописывать, воспримите мой комментарий именно с этой точки зрения */
for a, b, c in product(list_a, list_b, list_c): - красиво, да. Не буду брюзжать про импорт/производительность. Скорее всего внутри оно также элегантно и завернётся.
Я узнал новую функцию.
Как же легко будет спутать порядок переменной итератора и итерируемой сущности уже на 2+ вложенности, что Вам и статический анализатор не всегда покажет.
Итого: уменьшили читабельность(+/-), добавили поле для ошибки(однозначно)
":=" – в целом не новшество. В предложенном контексте - для меня читабельность уменьшена, вычисляемая/простая переменная объявлена непонятно где, в лучшем случае с комплексным комментарием "а мы тут ещё это не только ... но и будем использовать дальше как ..."
Красиво. Из пяти предложенных выбрал бы это самым полезным и читаемым, если бы не "|" как оператор объединения. x=1|2, 1|=2 . Воспримется спорно (смотрите первую строку комментария)
Что вы гады творите, это же может и не питонщик читать)
Не вижу тут "лайфхака", работа с сущностью не в лоб, через обёртку.
Полезность лично для меня - №1+№3, понял как это читать.
Полезность "лайфхаков" - давайте на всех курсах ребятам №5, через задницу это часто делают.
Первый "лайфхак" и правда заинтересовал, даже проверил
list_a = [i ** 2 for i in range(1000)]
list_b = [i ** 2 for i in range(1000)]
list_c = [i ** 2 for i in range(1000)]
def func1():
for a in list_a:
for b in list_b:
for c in list_c:
summ = a + b + c
if summ > 2_000_000:
print(a, b, c)
return
def func2():
for a, b, c in product(list_a, list_b, list_c):
summ = a + b + c
if summ > 2_000_000:
print(a, b, c)
return
Вывод:
4096 998001 998001
4096 998001 998001
Первый способ: 0:00:02.777251
Второй способ: 0:00:03.161027
Возможно, если циклов больше 3, то это имеет смысл (хотя слабо себе представляю такую конструкцию)
Возможно, если циклов больше 3, то это имеет смысл
Тут прелесть product в том, что он может работать не только с большим количеством списков, но и с заранее не известным количеством списков:
# Представьте, что это приходит из какого-то внешнего кода
# и мы заранее не знаем, сколько там будет списков
lists = [list_a, list_b, list_c]
for variant in product(*lists):
# Какой-то код, который умеет работать с кортежами неизвестной длины
print(*variant)
5 лайфхаков Python, которые сделают ваш код более читабельным и элегантным