Перейти к основному содержимому

Python лучшие практики

list - списки

Копирование списка (массива)

Через слайсы.

numbers = [1, 2, 3]
copy_numbers = numbers[:]

Реверсирование списка (массива)

чтобы записать список в обратном порядке достаточно использовать срез вида [::-1]

arr = [1, 2, 3, 4, 5, 6]
arr[::-1]
#[6, 5, 4, 3, 2, 1]

Удаление дубликатов из списка

Предположим у нас есть list

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

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

my_list = list(set(my_list))

В этом случает тип list превратиться в set, в нем по определению не может быть дубликатов потому что хеш-set. Но есть нюанс - порядок элементов будет рандомный.

Что делать если порядок элементов нужно сохранить просто удалив дубликаты?

Если расположение элементов имеет значение Самый простой и понятный метод:

list(dict.fromkeys(seq))

Самый быстрый метод, чуть сложней для понимания:

def uniq_nums(seq):
uniq = set()
uniq_add = uniq.add
return [item for item in seq if not item in uniq and not uniq_add(item)]

В случае когда не важно в каком порядке вернуться элементы:

list(set(seq))

Enumerate: вместо range(len(array))

Вы еще используете for i in range(len(array)) для доступа по индексам к данным последовательностей?
Если это так используйте enumerate. Это дает тот же результат, но намного понятней.

arr = ['a', 'b', 'c', 'd', 'e']

# Instead of this
for i in range(len(arr)):
print(i, arr[i])

# 0 a
# 1 b
# 2 c
# 3 d
# 4 e


# Use this
for i, val in enumerate(arr):
print(i, val)

# 0 a
# 1 b
# 2 c
# 3 d
# 4 e
  • обсуждение на reddit.com почему enumerate лучше.

Распаковка

Без заморочек, распаковываем списки / кортежи в отдельные переменные.

# Пример тупла
tpl = ('bla-bla', 1, 2, 3, 4, 'a', 'b')

# части элементов из множества
# получаем последний элемент (первые передаем в подстрочный)
*_, a, b = tpl

# a, b

# получаем первый и последний элементы
a, *_, b = tpl

# a, b

# получаем первые 2 элемента
a, b, *_ = tpl

# a, b

Date

Хорошей практикой для отображения даты и времени будет придерживаться стандарта ISO_8601.
Россия использует формат ГОСТ ИСО 8601-2001.

Дополнительные примеры можно посмотреть в официальной документации для модуля datetime isoformat

Стоит заметить, что по стандарту ISO 8601 "пробел" между указанием даты и времени запретили правилами ISO 8601-1:2019
Теперь разделитель буква "T".

Отображение даты и времени в коде через f-строку

from datetime import datetime

today = datetime.now()

# only day
print(f'{today:%Y-%m-%d}')
# 2023-01-10

# day n time
print(f'{today:%Y-%m-%dT%H:%M:%S}')
# 2023-01-10T23:06:48

# isoformat
datetime.now().replace(microsecond=0).isoformat()
# 2023-09-02T09:40:44

if else

Множественный or

по возможности заменяем на список

name = 'Alex'
if name == 'John', or name == 'Steeve' or name == 'Bill':
print(name)

if name in ('John', 'Steeve', 'Bill'):
print(name)

Булиевый if

a = b = d = c = e = True
if a and b and c and d and e:
print('All is True')

if all((a, b, c, d, e)): print('All is True')

# вариант для (хотя бы одного)
if any((a, b, c, d, e)): print('Any is True')

Избыток if

class User:
def __init__(self, group: str):
self.group = group

user = User(group="admin")

# нежелательный, хотя более понятный вариант
if user.group == "admin":
process_admin_recuest(user, request)
elif user.group == "manager":
process_manager_recuest(user, request)
elif user.group == "client":
process_client_recuest(user, request)

# непонятно почему более предпочитаемый варик
group_to_process = {
'admin': process_admin_recuest,
'manager': process_manager_recuest,
'client': process_client_recuest,
}
group_to_process[user.group](user, request)

Множественная итерация через map

# прогон x, y, z через map превращая их в инты.
x, y, z = map(int, (x, y, z))

Приведение типов

str to tuple / list

sites_urls = "some.url, second.com, third.com"

if isinstance(sites_urls, str):
sites_urls = tuple(sites_urls.split(', '))
print(sites_urls)