January 14, 2020

7 практических трюков в Python

Нет никаких сомнений, что Python можно назвать языком, испытавшим в последнее десятилетие значительный рост. Языком, который постоянно доказывает свою мощь.

Мы создали множество Python-приложений – от чат-ботов в Telegram до блокчейнов и небольших игр. Поистине Python обладает огромным количеством возможностей, и если вы только начали работать с ним, то сходу бывает сложно всё это ухватить.

Хотя, даже если вы программист, который переходит на Python с другого языка, или если вы учёный, который раньше работал с MATLAB, программирование на Python с использованием высокоуровневых абстракций – это совершенно новый для вас опыт.

Сегодня Python Academy расскажет о нескольких очень важных возможностях Python.

Большинство примеров будут работать только в третьей версии Python.

1. Сортировка словаря по значениям

Распространена практика использования словарей в качестве таблиц для хранения данных. Сортировка данных словаря по значениям ключей, а не самим ключам, нередко ставит в тупик. Задача решается довольно просто при помощи аргумента key для указания функции, которая будет вызываться на каждом элементе до сравнения:

>>> d = {'яблоки': 40, 'апельсины': 80, 'бананы': 70}
>>> sorted(d, key=d.get)
['яблоки', 'бананы', 'апельсины']

2. Нахождение наиболее частых элементов списка

Если необходимо найти несколько наиболее часто повторяющихся значений, лучше воспользоваться счетчиком Counter из библиотеки collections:

>>> from collections import Counter
>>> a = ['a', 'b', 'c', 'a', 'b', 'c', 'b', 'b', 'd', 'e', 'a']
>>> cnt = Counter(a)
>>> cnt.most_common(3)
[('b', 4), ('a', 3), ('c', 2)]

Метод Counter.most_common(x) возвращает x кортежей, в которых первое значение – элемент, а второе – количество его повторений.

3. Объединение списков без цикла

Как бы вы решили задачу объединения списков разной длины без обхода элементов цикла? Вот как это можно сделать с помощью стандартной функции sum, указав вторым аргументом пустой список, к которому будут прибавляться остальные подсписки:

>>> L = [[1, 2, 3], [4, 5], [6], [7, 8, 9]]
>>> sum(L, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Другой, пусть и менее краткий, но более эффективный способ – это применение модуля itertools:

import itertools

L = [[1, 2, 3], [4, 5], [6], [7, 8, 9]]

>>>list(itertools.chain.from_iterable(L))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Кстати, при работе с последовательностями многие полезные решения находятся в модулях стандартной библиотеки collections и itertools.

4. Удаление дубликатов в списке с сохранением порядка

Среди регулярно используемых трюков в Python – использование множества для удаления повторяющихся элементов в списке:

>>> items = [2, 2, 3, 3, 1]
>>> list(set(items))
[1, 2, 3]

Но множества – это неупорядоченные последовательности.

Часто необходимо сохранить порядок следования элементов. Для этого можно воспользоваться типом данных collections.OrderedDict, который похож на обычный словарь, но порядок, в котором ему были даны ключи. Итак, сделаем упорядоченный словарь, а дальше просто возьмем его ключи:

from collections import OrderedDict

items = [2, 2, 3, 3, 1]

>>> d = OrderedDict.fromkeys(items)
>>> list(d.keys())
[2, 3, 1]

5. Объединение строк

Нередко программисту приходится сталкиваться с конкатенацией строк при помощи знака сложения. Создание строки из списка нескольких подстрок удобнее осуществить при помощи строкового метода join:

>>> a = ["Python", "-", "прекрасный", "язык."]
>>> " ".join(a)
'Python - прекрасный язык.'

Вот пример посложнее – конвертирование списка чисел в строку:

>>> numbers = [1, 2, 3, 4, 5]
>>> ', '.join(map(str, numbers))
'1, 2, 3, 4, 5'

Не забывайте, что метод join работает быстрее чем цикл.

6. Функция zip

Функция zip создаёт итератор, который комбинирует элементы нескольких списков. Это позволяет осуществлять параллельный обход списков в циклах for или, например, выполнять параллельную сортировку.

Вот пример работы с функцией zip:

>>> list_a = [0, 1, 2]
>>> list_b = ['zero', 'one', 'two']
>>> list_c = ['cero', 'uno', 'dos']
>>> list(zip(list_a, list_b, list_c))
[(0, 'zero', 'cero'), (1, 'one', 'uno'), (2, 'two', 'dos')]

>>> for a, b, c in zip(list_a, list_b, list_c):
...     print(f'{a} is {b} in English and {c} in Spanish.')
... 
0 is zero in English and cero in Spanish.
1 is one in English and uno in Spanish.
2 is two in English and dos in Spanish.

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

>>> z = list(zip(list_a, list_b, list_c))
>>> a, b, c = zip(*z)
>>> a
(0, 1, 2)
>>> b
('zero', 'one', 'two')
>>> c
('cero', 'uno', 'dos')

7. Функция enumerate

На первый взгляд функция enumerate может показаться сложной, но, если с ней разобраться, оказывается, что она способна пригодиться во многих случаях. Функция enumerate позволяет создавать автоматический счётчик, который часто используется в циклах for.

В таких циклах не нужно создавать и инкрементировать переменную-счётчик, используя конструкции вроде counter = 0 и counter += 1

Функции zip и enumerate – это два мощнейших инструмента, применяемых при конструировании циклов for:

>>> upperCase = ['A', 'B', 'C', 'D', 'E', 'F']
>>> lowerCase = ['a', 'b', 'c', 'd', 'e', 'f']

>>> for count, (upper, lower) in enumerate(zip(upperCase, lowerCase), 1):
...     print(f'{count}: {upper} and {lower}.')
... 
1: A and a.
2: B and b.
3: C and c.
4: D and d.
5: E and e.
6: F and f.

В данном случае переменная count используется как автоматический счетчик.

Веселый бонус в конце

Дочитали статью? Наверняка многие из вас знают про Дзен Python, выводимый интерпретатором по команде import this. В третьей версии Python спрятаны и некоторые другие «пасхалки»:

import antigravity
import __hello__

Материал подготовлен образовательной организацией Python Academy.