Как записать цикл в одну строку python
Перейти к содержимому

Как записать цикл в одну строку python

  • автор:

Как вывести цикл в одну строку питон

1) Функция print() имеет параметр end , указывающий какой символ или какую строку выводить после вывода каждого значения (по дефолту переходом на новую строку, т.е. строкой ‘\n’ ). Укажите необходимый разделитель (например пробельной строкой ‘ ‘ ):

for x in range(0, 5): print(x, end=' ') # => 0 1 2 3 4 

2) Перед выводом данные можно агрегировать в массив, который затем методом join() соединяем и выводим одной строкой:

array = [] for x in range(0, 5): array.append(str(x)) # => [0, 1, 2, 3, 4] print(' '.join(array)) # => 0 1 2 3 4 

При этом все элементы должны быть строковыми объектами, поэтому в цикле мы приводили числа к строкам str(x) .

5++ способов в одну строку на Python решить первую задачу Проекта Эйлера

Однажды меня посетила мысль, а что если попробовать решить первую задачу Проекта Эйлера всевозможными способами, но с условием, что решение должно быть в одну строку. В итоге получилось более пяти однострочных решений с применением Filter, Map, Reduce, Generator Expression и т.д. В этой статье я покажу то, к чему я пришёл.

Это моя первая статья. Стоит отнестись к ней настороженно. Уникальные решения будут оформлены в отдельные пункты. Менее уникальные — в подпункты.

Условие задачи

Если выписать все натуральные числа меньше 10, кратные 3 или 5, то получим 3, 5, 6 и 9. Сумма этих чисел равна 23.

Найдите сумму всех чисел меньше 1000, кратных 3 или 5.

00 — Базовое решение

Прежде чем перейти непосредственно к однострочным решениям, разумно было бы упомянуть сначала стандартное, классическое решение:

result = 0 for i in range(1, 1000): if i%3 == 0 or i%5 == 0: result += i print(result) # => 233168

Перебираем последовательность чисел от 1 до 999. Если перебираемое число делится на 3 или на 5 без остатка от деления, то прибавляем каждое такое число в заранее объявленную переменную result .

01 — Generator Expression. Выражение-генератор

print(sum(i for i in range(1, 1000) if i%3 == 0 or i%5 == 0)) # => 233168

Числа из последовательности от 1 до 999, делящиеся на 3 или на 5 без остатка от деления, собираются в генератор. Затем функция sum() складывает содержимое генератора.

01.a — List Comprehension. Выражение на основе списка
print(sum([i for i in range(1, 1000) if i%3 == 0 or i%5 == 0])) # => 233168

В отличии от предыдущего, здесь выражение дополнительно помещается в список. Стоило упомянуть этот вариант, так как он довольно часто встречается в различных статьях.

01.b — Set Comprehension. Выражение на основе множества
print(sum()) # => 233168

Тоже, что и в предыдущем, но вместо списка здесь множество.

02 — Filter

print(sum(filter(lambda i: i%3 == 0 or i%5 == 0, range(1, 1000)))) # => 233168

Функция filter схожа по принципу работы с выражением-генератором. Функция лямбда применяется к каждому элементу последовательности чисел от 1 до 999. Все числа последовательности, делящиеся на 3 или на 5 без остатка от деления, возвращаются, затем суммируются функцией sum() .

03 — Map

print(sum(map(lambda i: i if i%3 == 0 or i%5 == 0 else 0, range(1, 1000)))) # => 233168

Перебираемые числа последовательности от 1 до 999, делящиеся на 3 или 5 без остатка от деления, остаются без изменений, все остальные числа заменяются на ноль. Полученная последовательность суммируется функцией sum() .

04 — Reduce

from functools import reduce print(reduce(lambda x, y: x+y if y%3 == 0 or y%5 == 0 else x, range(1, 1000), 0)) # => 233168

Из всей подборки, этот вариант «очень не очень». Как по степени реализации, так и по времени выполнения(но об этом попозже).
Если в reduce указан инициализатор(в нашем случае ноль), то он становится накопителем. К нему по очереди прибавляются только те числа из последовательности от 1 до 999, которые делятся на 3 или на 5 без остатка от деления. Если из функции reduce убрать инициализатор ноль, то инициализатором станет крайний левый элемент последовательности.

05 — Однострочное решение на основе множества

print(sum(set(range(3, 1000, 3)) | set(range(5, 1000, 5)))) # => 233168

Самое элегантное решение, как по красоте написания, так и по времени выполнения.
Последовательность чисел от 1 до 999, кратную трём, помещаем во множество и объединяем со множеством, содержащим в себе последовательность чисел от 1 до 999, кратную пяти. Содержимое, полученного множества суммируем функцией sum() .

05.a — Ещё одно однострочное решение на основе множества
print(sum( <*range(3, 1000, 3)>| <*range(5, 1000, 5)>)) # => 233168

Похожий вариант на предыдущий, но, если использовать фигурные скобки, то последовательность чисел от 1 до 999, кратную трём и последовательность чисел от 1 до 999, кратную пяти, нужно распаковывать.

05.b — И ещё одно однострочное решение на основе множества
print(sum(set(range(3, 1000, 3)).union(range(5, 1000, 5)))) # => 233168

Создаём множество, с последовательностью чисел от 1 до 999, кратную трём и присоединяем к нему последовательность чисел от 1 до 999, кратную пяти. Затем функцией sum() суммируем.

05.c И последнее однострочное решение на основе множества
print(sum(set([*range(3, 1000, 3)] + [*range(5, 1000, 5)]))) # => 233168

По аналогии с предыдущими. Распаковываем последовательности чисел в списки. Складываем списки. Оборачиваем во множество. Затем суммируем функцией sum() .

Смотрим на скорость выполнения каждого однострочного решения

Если проверить скорость выполнения каждого однострочного решения в командной строке, при помощи timeit, получим следующие значения в микросекундах:

sum(i for i in range(1, 1000) if i%3 == 0 or i%5 == 0) # 203 usec sum([i for i in range(1, 1000) if i%3 == 0 or i%5 == 0]) # 181 usec sum() # 189 usec sum(filter(lambda i: i%3 == 0 or i%5 == 0, range(1, 1000))) # 306 usec sum(map(lambda i: i if i%3 == 0 or i%5 == 0 else 0, range(1, 1000))) # 313 usec reduce(lambda x, y: x+y if y%3 == 0 or y%5 == 0 else x, range(1, 1000), 0)# 324 usec sum(set(range(3, 1000, 3)) | set(range(5, 1000, 5))) # 47 usec sum( <*range(3, 1000, 3)>| <*range(5, 1000, 5)>) # 47 usec sum(set(range(3, 1000, 3)).union(range(5, 1000, 5))) # 41 usec sum(set([*range(3, 1000, 3)] + [*range(5, 1000, 5)])) # 43 usec

Методика расчёта: python -m timeit «выражение»

Быстрее всего справились с задачей последние четыре варианта.

Заключение

Всего получилось 5 уникальных + 5 не уникальных решений. Благодаря этой задаче у меня появилось более устойчивое понимание работы функций Filter, Map, Reduce. И если раньше я недоумевал, почему функцию Reduce убрали из основного модуля, то теперь я не сомневаюсь в правильности этого решения.

В статье я старался отойти от популярного шаблона повествования «точность на грани бесполезности». Где предложения набиты под завязку «тяжёлыми» терминами, а из знакомого там только союзы и предлоги. Не уверен, что у меня получилось.

8 способов свести ваши функции Python в одну строку

Да, мы можем это сделать. Оба блока кода выполняют одно и то же, но нижний расположен в одну строку. Я уверен, что вы не знали о том, что так можно делать!

2) Лямбда-функции

Лямбда-функции — это небольшие анонимные функции, которые мы можем записать в одной строке, используя ключевое слово lambda. Синтаксис:

lambda inputs: return_value
def greet(): return ‘hello’ # this is the same as greet = lambda : ‘hello’
def add10(n): return n + 10 # this is the same as add10 = lambda n: n+10
def add(a, b): return a + b # this is the same as add = lambda a, b: a+b
3) Использование точек с запятой вместо новых строк
def hello(): x = 1 y = 2 print(x, y) # this function spans 4 lines
def hello():x=1;y=2;print(x,y) # now it spans 1 line

Да, мы можем это сделать! Однако, обратите внимание, что это не сработает, если у вас больше 1 двоеточия, например: использование блоков if-else, циклов for и т.д. Поэтому используйте этот метод экономно и только в крайнем случае.

4) Понимание списка / словаря / множества — сжатие циклов

Понимание списка / словаря / множества — это метод в Python, который позволяет нам создать список / словарь / множество в 1 строке кода. Синтаксис:

# list comprehension [expression for var in iterable if condition] # dict comprehension

# given some numbers, we want to square them all lis = [1, 2, 3, 4, 5] # using a normal for loop new = [] for n in lis: new.append(n**2) # new = [1, 4, 9, 16, 25] # using list comprehension new = [n**2 for n in lis] # new = [1, 4, 9, 16, 25]

# given some numbers, we want to create a dict # where keys are numbers, and values are squares lis = [1, 2, 3, 4, 5] # using a normal for loop new = <> for n in lis: new[n] = n**2 # new = # using dict comprehension new = # new =

# given some numbers, find unique odd numbers lis = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5] # using a normal for loop new = set() for n in lis: if n%2 == 1: new.add(n) # # using set comprehension new = #

5) Блоки if—else в виде тернарного оператора

# if else var = X if condition else Y # if-elif-else var = A if else B if else C # if-elif-elif-else var = A if else B if else C if else D

Тернарный оператор позволяет нам сконденсировать блоки if-else в одну строку. Несколько примеров:

# normal if-else block if x==5: y = ‘hello’ else: y = ‘hi’ # using the ternary operator y = ‘hello’ if x==5 else ‘hi’

# normal if-elif-else block if x==5: y = ‘hello’ elif x==6: y = ‘hola’ else: y = ‘hi’ # using the ternary operator y = ‘hello’ if x==5 else ‘hola’ if x==6 else ‘hi’

# normal if-elif-elif-else block if x==5: y = ‘hello’ elif x==6: y = ‘hola’ elif x==7: y = ‘nihao’ else: y = ‘hi’ # using the ternary operator y = ‘hello’ of x==5 else ‘hola’ if x==6 else ‘nihao’ if x==7 else ‘hi’

6) Объединение методов в цепочку — несколько методов в одной строке

x = x.method1() x = x.method2() x = x.method3() # using method chaining x = x.method1().method2().method3()

Мы можем использовать цепочку методов, как в приведённом выше блоке кода, если мы хотим сконденсировать несколько вызовов методов в 1 строку кода. Например:

# we want to turn this string = ‘\n\nApple Orange Pear\n\n’ # into lis = [‘apple’, ‘orange’, ‘pear’]

# doing this using multiple method calls lis = string.strip() lis = lis.lower() lis = lis.split() # lis = [‘apple’, ‘orange’, ‘pear’]

# same method calls, but using method chaining lis = string.strip().lower().split() # lis = [‘apple’, ‘orange’, ‘pear’]

7) Рекурсия (более продвинутый материал)

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

Допустим, мы хотим сгенерировать n-е число Фибоначчи. Числа Фибоначчи — это серия чисел, 1) которые начинаются с [0, 1] 2) где каждое новое число является суммой двух предыдущих.

# iteratively (non-recursively) def fib(n): lis=[0,1]; [lis.append(lis[-1]+lis[-2]) for i in range(n-2)]; return lis[n-1] # recursively def fib(n): return n-1 if n

Заметили, что рекурсивное решение значительно короче и проще в управлении (полностью игнорируя временную сложность)? Это становится более очевидным, когда мы пытаемся свести более сложные функции в 1 строку.

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

8) Метод обмана — использование ‘exec’

Допустим, вы застряли и совершенно не представляете, как свести вашу функцию в 1 строку, но хотите проложить свой путь до конца. Этот метод для вас!

# a normal function def f(x): x += 10 return x # using exec exec(‘def f(x):\n x += 10\n return x’)

Встроенный метод exec принимает строку и выполняет всё, что содержит строка, как фактический код Python. Этот метод полезен, если вы совершенно отчаялись в процессе сжатия функции в 1 строку.

Заключение

8-й способ технически может свести каждую отдельную функцию в 1 строку кода Python, но это абсолютно ужасная практика, и, пожалуйста, не делайте этого в коде производственного уровня (ваши коллеги возненавидят вас)

Надеюсь, сегодня вы узнали что-то новое!

Как сделать цикл for и условие if in в одну строку?

вопрос следующего типа.
цикл for с последующим условием if in будет использоваться более 1000 раз.
Можно ли как то сократить в 1 строку?

  • Вопрос задан 02 апр. 2023
  • 781 просмотр

Комментировать
Решения вопроса 1

Vindicar

цикл for с последующим условием if in будет использоваться более 1000 раз.
Можно ли как то сократить в 1 строку?

Можешь пояснить, какая вообще связь между длиной кода и числом использований?

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

Сейчас выглядит как будто ты пишешь этакого чат-бота для терминала. Если я прав, то длинная цепочка из if-elif-elif тут не подойдёт.

Но если прямо невтерпёж, то

if any(word in text for word in ["привет", "хай"]):

Ответ написан 02 апр. 2023
Нравится 2 6 комментариев

RoMoN777

RoMoN @RoMoN777 Автор вопроса
от души эта строка то что мне нужно.
да делаю чат бота телеграмм.

Vindicar

RoMoN, лучше используй существующие средства для выбора команды. У большинства библиотек что-то да есть.

А как в таком однострочнике расположить break ?

Vindicar

hulitolku, никак, да и не надо. Как ты это себе вообще представляешь?

Vindicar, Ну допустим список [«привет», «хай»] состоит из десятки тысяч элементов, и чтобы не тратить время, пробегая по всему списку, если например слово найдется в самом начале, то брейк будет прерывать цикл.

Vindicar

hulitolku, почитай как работает any(). А вообще в таких случаях нужен не линейный перебор списка, а быстрый поиск в отсортированной коллекции, тут уже лучше свою функцию для проверки вхождения написать.

Ответы на вопрос 1

RimMirK

Вроде человек. Вроде учусь. Вроде пайтону
походу, никак

C:\Users\User>py Python 3.10.8 (tags/v3.10.8:aaaf517, Oct 11 2022, 16:50:30) [MSC v.1933 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> text = '123' >>> print('hello') if command in text for command in ["привет", "хай"] File "", line 1 print('hello') if command in text for command in ["привет", "хай"] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SyntaxError: expected 'else' after 'if' expression >>> print('hello') if command in text else pass for command in ["привет", "хай"] File "", line 1 print('hello') if command in text else pass for command in ["привет", "хай"] ^^^^ SyntaxError: invalid syntax >>> print('hello') if command in text else . for command in ["привет", "хай"] File "", line 1 print('hello') if command in text else . for command in ["привет", "хай"] ^^^ SyntaxError: invalid syntax >>> print('hello') if command in text else print('',end='') for command in ["привет", "хай"] File "", line 1 print('hello') if command in text else print('',end='') for command in ["привет", "хай"] ^^^ SyntaxError: invalid syntax >>> command print('hello') if command in text else print('',end='') for command in ["привет", "хай"] File "", line 1 command print('hello') if command in text else print('',end='') for command in ["привет", "хай"] ^^^^^ SyntaxError: invalid syntax >>> print('hello') if command in text else print('',end='') command for command in ["привет", "хай"] File "", line 1 print('hello') if command in text else print('',end='') command for command in ["привет", "хай"] ^^^^^^^ SyntaxError: invalid syntax >>> print('hello') if command in text else print('',end='') for command in ["привет", "хай"] File "", line 1 print('hello') if command in text else print('',end='') for command in ["привет", "хай"] ^^^ SyntaxError: invalid syntax

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *