30 уловок на языке Python, которые сделают вас лучшим программистом
Существует множество облегчающих жизнь программиста на Python лайфхаков. Даже если вы уже овладели языком, вы все равно должны это прочитать. Обсудить Перевод публикуется с сокращениями, автор оригинальной статьи – Erik van Baaren. Многоточие Python – это последовательность из трех точек, часто используемая в естественных языках. Но чего вы, возможно, не знаете – это еще и валидный объект в Python: Применяется он преимущественно в операциях нарезки матриц в NumPy. Однако можно использовать его вместо обычного pass в качестве плэйсхолдера в функции, которую еще не реализовали: Вот валидный код Python, и выглядит он теперь не так уж плохо. Начиная с версии 3.7, Python поставляется с классами данных. У них есть несколько преимуществ по сравнению с обычными классами или другими альтернативами: Пример класса данных в работе: Одним из самых ранних Python pep является PEP-20. Это список из 19 тезисов по программированию на Python, который называется «The Zen of Python». Данные правила датируются 2004 годом и, в свою очередь, основаны на PEP-8. Такая пасхалочка уже давно присутствует в Python и перечисляет набор правил: Так что пока у вас есть Python REPL, можете просматривать эти правила на экране. Иногда именованию функции не стоит уделять особого внимания. Например, если вы уверены, что она будет использована только раз. Для таких случаев Python предлагает применять анонимные функции, также называемые лямбда-функциями. Лямбда-функция может быть назначена переменной, создавая краткий способ определения функции: Это становится более интересным, когда необходимо использовать функцию в качестве аргумента. В таких случаях она часто используется только один раз. Как известно, map применяет функцию ко всем элементам итерируемого объекта. Мы можем использовать лямбду при вызове map: Этот кусок кода встречается часто. Например, когда требуется применить операцию к каждому элементу итеративного объекта. В данной ситуации использование map() в сочетании с лямбда-функцией является кратким и эффективным. List comprehension может заменить неэстетичные циклы, используемые для заполнения списка. Синтаксис выглядит следующим образом: Простейший пример заполнения списка последовательностью чисел: Поскольку здесь можно использовать выражения, вам доступна работа с математикой: Вызов внешней функции: И, наконец, вы сможете использовать «if» для фильтрации списка. В этом случае будут сохранены только те значения, которые делятся на 2: Этот аккуратный трюк поможет сэкономить несколько строк кода: Такую штуку используют нечасто, но если данные уже находятся в словаре, для форматирования именованных строк пригодится следующий прием: Вы даже можете использовать функцию locals(), но в последних версиях Python придется обращаться к f-строкам следующим образом: Помните основной синтаксис list comprehensions? Если expression может быть любым валидным выражением Python, оно также может быть и другим list comprehension. Это полезно, когда необходимо создать матрицу: Или, если хотите «разгладить» предыдущую матрицу: Первая часть цикла по матрице m, а вторая – цикл по элементам каждого вектора. Для принудительного использования аргументов ставьте символ звездочки перед ними, заставляя все аргументы стать ключевыми: Вы можете получить результат последнего выражения в Python REPL с помощью оператора подчеркивания, например, в Python REPL это выглядит следующим образом: Прием работает и в оболочке IPython. Чтобы ваши пользователи не могли запустить скрипт в несовместимой версии, в коде стоит проверить наличие актуальной версии Python. Проведите простую проверку: Декоратор – это обертка вокруг функции, которая определенным образом изменяет ее поведение. Существуют варианты использования декораторов, и вы, возможно, уже применяли их раньше при работе с такими фреймворками, как Flask. Давайте создадим собственного декоратора: Внутри print_argument мы определяем функцию-обертку. Она выводит аргумент и имя вызываемой функции, выполняет фактическую функцию и возвращает ее результат, как если бы функция вызывалась «обычно». С помощью @print_argument мы применяем наш декоратор к функции. Декоратор может быть повторно использован и для других функций. Давайте создадим собственного декоратора: Функции в Python могут возвращать более одной переменной без применения словаря, списка или класса. Это работает так: Здесь возвращается кортеж. С тем же эффектом можно было бы написать return (name, birthdate). Это нормально для ограниченного количества возвращаемых значений. Но все, что превышает 3 значения, должно быть помещено в класс (data). Начиная с Python 3.5, стало проще объединять словари. Если встречаются дублирующиеся ключи – в первом словаре они будут перезаписаны. Синтаксис нарезания таков: Start, stop и step необязательны. У них есть дефолтные значения, которые активируются, если не заполнить параметры: Вот несколько примеров: С помощью sys.getsizeof() можно проверить использование памяти объектом: Огромный список всего 48 байт, потому что функция range возвращает класс, который ведет себя как список. В вопросе памяти range эффективнее, чем использование актуального списка чисел. Некоторые функции требуют длинного списка аргументов. Этого следует избегать (например, с помощью классов данных), хотя это не всегда зависит от вас. Существует другой вариант – создать словарь с именованными аргументами и передать его функции. Так ваш код станет более читабельным. Распаковать словарь можно, используя префикс **: Аналогично можно использовать * для распаковки массива и передачи его содержимого в качестве аргументов функции: Если хотите быстро получить красивый заголовок, сделайте так: Вы можете разбить строку на список строк. В этом случае разбиение происходит по символу пробела: Чтобы разделить по пустому месту, не нужно передавать в split никаких аргументов – используйте mystring.split(). Split также имеет второй параметр, называемый maxsplit, который определяет максимальное количество разбиений. По умолчанию он равен -1 (без ограничений). Вот пример, с ограничением разбиения на 1: Создание строки из списка и установка пробелов между каждым словом: Все сводится к тому, что функция String.join() может присоединять не только списки, но и любой iterable. Помещение его внутрь строки предотвращает реализацию одной и той же функциональности в нескольких местах. JMESpath – это язык запросов для JSON, который позволяет получать необходимые данные из документа или словаря JSON. Библиотека доступна как для Python, так и для других ЯП, что расширяет ее возможности. Вот несколько примеров кода для общего представления: Вы можете использовать slice-нотацию, чтобы перевернуть строку или список. При отрицательном значении шага, элементы меняются местами: Создавая набор с помощью функции set(), вы получаете все уникальные элементы из списка или объекта: В словарь можно поместить что угодно – вы не ограничены числами или строками. Можете поместить списки внутрь словаря и получить доступ к вложенным значениям: Это еще один способ сделать код более кратким и сохранить его читабельность: А вот пример: Используйте Counter из библиотеки коллекций, чтобы получить словарь с подсчетом всех уникальных элементов в списке: Создавайте еще более читаемый и аккуратный код: Модуль python-dateutil предоставляет мощное расширение для стандартного datetime. Устанавливается он следующим образом: Вот пример парсинга даты из логов: Такой синтаксис имеет данная встроенная функция: Ниже видите пример с использованием списков: Словарю нужны ключ и значение: Определяем ключ и значение в expression. Синтаксис set comprehension не сильно отличается от list comprehension. Мы просто используем фигурные скобки вместо квадратных: Пример: В современном динамичном мире важно знать как можно больше хитростей, ускоряющих рутинную работу разработчика. Рассмотренная подборка отвечает всем требованиям повышенного уровня сложности и при должном количестве потраченного времени сможет вырастить из вас профессионала – главное не сдавайтесь! Удачи! Дополнительный материал:1. Многоточие в Python
>>> ... Ellipsis
def my_awesome_func(): ...
2. Data classes
from dataclasses import dataclass @dataclass class Card: rank: str suit: str card = Card("Q", "hearts") print(card == card) # True print(card.rank) # 'Q' print(card) Card(rank='Q', suit='hearts')
3. The Zen of Python
4. Анонимные функции
>>> add_one = lambda x: x + 1 >>> add_one(3) 4
>>> numbers = [1, 2, 3, 4] >>> times_two = map(lambda x: x * 2, numbers) >>> list(times_two) [2, 4, 6, 8] >>>
5. List Comprehensions
[ expression for item in list if conditional ]
mylist = [i for i in range(10)] print(mylist) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
squares = [x**2 for x in range(10)] print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
def some_function(a): return (a + 5) / 2 my_formula = [some_function(i) for i in range(10)] print(my_formula) # [2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0]
filtered = [i for i in range(20) if i%2==0] print(filtered) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
6. Замена переменных на месте
a = 1 b = 2 a, b = b, a print (a) # 2 print (b) # 1
7. Форматирование именованных строк
8. Nested list comprehensions
[ expression for item in list if conditional ]
>>> [[j for j in range(3)] for i in range(4)] [[0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2]]
>>> [value for sublist in m for value in sublist] [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]
9. Обязательные аргументы
>>> def f(*, a, b): ... print(a, b) ... >>> f(1, 2) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() takes 0 positional arguments but 2 were given >>> f(a=1, b=2) 1 2 >>>
10. Использование подчеркивания в REPL
>>> 3 * 3 9 >>> _ + 3 12
11. Проверка необходимой версии Python
if not sys.version_info > (2, 7): # berate your user for running a 10 year # python version elif not sys.version_info >= (3, 5): # Kindly tell your user (s)he needs to upgrade # because you're using 3.5 features
12. Декорируем функции
def print_argument(func): def wrapper(the_number): print("Argument for", func.__name__, "is", the_number) return func(the_number) return wrapper @print_argument def add_one(x): return x + 1 print(add_one(1))
Argument for add_one is 1 2
13. Возврат нескольких значений
def get_user(id): # fetch user from database # .... return name, birthdate name, birthdate = get_user(4)
14. Объединение словарей
dict1 = { 'a': 1, 'b': 2 } dict2 = { 'b': 3, 'c': 4 } merged = { **dict1, **dict2 } print (merged) # {'a': 1, 'b': 3, 'c': 4} # Python >= 3.9 only merged = dict1 | dict2 print (merged) # {'a': 1, 'b': 3, 'c': 4}
15. Нарезка списка
a[start:stop:step]
# We can easily create a new list from # the first two elements of a list: first_two = [1, 2, 3, 4, 5][0:2] print(first_two) # [1, 2] # And if we use a step value of 2, # we can skip over every second number # like this: steps = [1, 2, 3, 4, 5][0:5:2] print(steps) # [1, 3, 5] # This works on strings too. In Python, # you can treat a string like a list of # letters: mystring = "abcdefdn nimt"[::2] print(mystring) # 'aced it'
16. Использование памяти
import sys mylist = range(0, 10000) print(sys.getsizeof(mylist)) # 48
import sys myreallist = [x for x in range(0, 10000)] print(sys.getsizeof(myreallist)) # 87632
17. Использование * и ** для распаковки аргументов функций
>>> def f(a, b): ... print(a, b) ... >>> args = { "a": 1, "b": 2 } >>> f(**args) 1 2
>>> def f(a, b, c): ... print(a, b, c) ... >>> l = [1, 2, 3] >>> f(*l) 1 2 3
18. Строка – заголовок
mystring = "10 awesome python tricks" print(mystring.title()) '10 Awesome Python Tricks'
19. Разбиение строки в список
mystring = "The quick brown fox" mylist = mystring.split(' ') print(mylist) # ['The', 'quick', 'brown', 'fox']
>>> mystring.split(' ', 1) ['The', 'quick brown fox']
20. Создание строки из списка строк
mylist = ['The', 'quick', 'brown', 'fox'] mystring = " ".join(mylist) print(mystring) # 'The quick brown fox'
21. Query JSON
>>> import jmespath >>> persons = { ... "persons": [ ... { "name": "erik", "age": 38 }, ... { "name": "john", "age": 45 }, ... { "name": "rob", "age": 14 } ... ] ... } >>> jmespath.search('persons[*].age', persons) [38, 45, 14]
22. Реверс строк и списков
revstring = "abcdefg"[::-1] print(revstring) # 'gfedcba' revarray = [1, 2, 3, 4, 5][::-1] print(revarray) # [5, 4, 3, 2, 1]
23. Получение уникальных элементов из списка или строки
mylist = [1, 1, 2, 3, 4, 5, 5, 5, 6, 6] print (set(mylist)) # {1, 2, 3, 4, 5, 6} # And since a string can be treated like a # list of letters, you can also get the # unique letters from a string this way: print (set("aaabbbcccdddeeefff")) # {'a', 'b', 'c', 'd', 'e', 'f'}
24. Валидные значения словаря
>>> a = { 'sub_dict': { 'b': True }, 'mylist': [100, 200, 300] } >>> a['sub_dict']['b'] True >>> a['mylist'][0] 100
25. Тернарный оператор условного присваивания
[on_true] if [expression] else [on_false]
x = "Success!" if (y == 2) else "Failed!"
26. Подсчет вхождений в список
from collections import Counter mylist = [1, 1, 2, 3, 4, 5, 5, 5, 6, 6] c = Counter(mylist) print(c) # Counter({1: 2, 2: 1, 3: 1, 4: 1, 5: 3, 6: 2}) # And it works on strings too: print(Counter("aaaaabbbbbccccc")) # Counter({'a': 5, 'b': 5, 'c': 5})
27. Цепочки операторов сравнения
x = 10 # Instead of: if x > 5 and x < 15: print("Yes") # yes # You can also write: if 5 < x < 15: print("Yes") # Yes
28. Работа с датами
pip3 install python-dateutil
from dateutil.parser import parse logline = 'INFO 2020-01-01T00:00:01 Happy new year, human.' timestamp = parse(logline, fuzzy=True) print(timestamp) # 2020-01-01 00:00:01
29. Использование map()
map(function, something_iterable)
def upper(s): return s.upper() mylist = list(map(upper, ['sentence', 'fragment'])) print(mylist) # ['SENTENCE', 'FRAGMENT'] # Convert a string representation of # a number into a list of ints. list_of_ints = list(map(int, "1234567")) print(list_of_ints) # [1, 2, 3, 4, 5, 6, 7]
30. Словарь и set comprehensions
>>> {x: x**2 for x in (2, 4, 6)} {2: 4, 4: 16, 6: 36}
{ <expression> for item in list if <conditional> }
>>> {s for s in range(1,5) if s % 2} {1, 3}
Заключение
- 1 views
- 0 Comment
Свежие комментарии