8 способов свести ваши функции Python в одну строку
1) Опустить символ новой строки после ключевого слова‘def’
def hello():
print('hello')
def hello():print('hello')
Да, мы можем это сделать. Оба блока кода выполняют одно и то же, но нижний расположен в одну строку. Я уверен, что вы не знали о том, что так можно делать!
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
{key:value for var in iterable if
# set comprehension
{expression for var in iterable if
Несколько примеров:
# 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 = {1:1,2:4,3:9,4:16,5:25}
# using dict comprehension
new = {n:n**2 for n in lis} # new = {1:1,2:4,3:9,4:16,5:25}
# 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) # {1, 2, 3, 4, 5}
# using set comprehension
new = {n for n in lis if n%2==1} # {1, 2, 3, 4, 5}
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<=2 else fib(n-1)+fib(n-2)
Заметили, что рекурсивное решение значительно короче и проще в управлении (полностью игнорируя временную сложность)? Это становится более очевидным, когда мы пытаемся свести более сложные функции в 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, но это абсолютно ужасная практика, и, пожалуйста, не делайте этого в коде производственного уровня (ваши коллеги возненавидят вас)
Надеюсь, сегодня вы узнали что-то новое!