Практические и эффективные методы программирования, которые я обычно использую, повысили мою эффективность и производительность при разработке программного обеспечения.

Печать списков в виде столбцов

Используйте F-strings для форматирования отпечатков. Например, мы можем использовать операторы < или > в сочетании с целым числом, чтобы выровнять строки по левому или правому краю с конечным пробелом соответственно. По сути, мы видим отпечатки очень похожими на столбцы.

food = ["Vanilla Ice Cream", "Hot Fudge", "Strawberry Sundae"]
qty = [1, 1, 1]
size = ["16oz", "16oz", "16oz"]
price = ["$7.99", "$6.99", "$7.99"]

# Header
print(f"{'Food':<20} {'Quantity':<10} {'Size':<10} {'Price':<10}\n")

# Body
for f, q, s, p in zip(food, qty, size, price):
    print(f"{f:<20} {q:<10} {s:<10} {p:<10}")
Food                 Quantity   Size       Price     

Vanilla Ice Cream    1          16oz       $7.99     
Hot Fudge            1          16oz       $6.99     
Strawberry Sundae    1          16oz       $7.99

Использование словарных понятий

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

ratings = [4.57, 4.43, 4.98]
books = ["Moby-Dick", "Pride and Prejudice", "The Catcher in the Rye"]

book_ratings = {book: rating for book, rating in zip(books, ratings)}

print(book_ratings)
{'Moby-Dick': 4.57, 'Pride and Prejudice': 4.43, 'The Catcher in the Rye': 4.98}
reversed_book_ratings = {rating: book for book, rating in book_ratings.items()}

print(reversed_book_ratings)
{4.57: 'Moby-Dick', 4.43: 'Pride and Prejudice', 4.98: 'The Catcher in the Rye'}
lbs = [40.0, 45.0, 35.0]
to_kgs = lambda x: f"{(x * 0.453592):.2f} kg"

weights = {f"{lb} lb": to_kgs(lb) for lb in lbs}

print(weights)
{'40.0 lb': '18.14 kg', '45.0 lb': '20.41 kg', '35.0 lb': '15.88 kg'}

Объединение словарей быстрее

Из библиотеки collections мы можем импортировать ChainMap для объединения двух словарей.

from collections import ChainMap

home_address = {"street": "21 2nd Street", "city": "New York", "state": "NY", "zipcode": "10021"}
home_owner = {"first_name": "John", "last_name": "Doe"}

address = ChainMap(home_address, home_owner)

print(address)
ChainMap({'street': '21 2nd Street', 'city': 'New York', 'state': 'NY', 'zipcode': '10021'}, {'first_name': 'John', 'last_name': 'Doe'})

Мы можем получить доступ к значениям, используя метод .get(key, default value). Это более pythonic и полезно для отладки, чем через dictionary[key].

print(f"Street: {address.get('street', 'N/A')}")
print(f"First Name: {address.get('first_name', 'N/A')}")
Street: 21 2nd Street
First Name: John

Другой способ объединить словари на месте — использовать оператор |=. Операция на месте просто изменяет содержимое данной переменной напрямую, не создавая копии. Следовательно, он будет перезаписывать или повторно использовать выделенную в данный момент память для этой переменной.

home_address |= home_owner

print(home_address)
{'street': '21 2nd Street', 'city': 'New York', 'state': 'NY', 'zipcode': '10021', 'first_name': 'John', 'last_name': 'Doe'}

Доступ к значениям аналогичен методу, показанному ранее. Существуют и другие способы объединения словарей, но эти два — лично мой выбор.

Использование тернарных операторов

Эти операторы известны своими однострочными приемами, которые делают ваш код более читабельным и компактным.

slack = True
todo = "study" if not slack else "sleep"

knowledge = 0
knowledge += 1 if todo == "study" else 0

def smaller(a, b):
    return [a, b][a > b]

print(f"To-do: {todo}")
print(f"Knowledge: {knowledge}")
print(f"smaller(1, 2): {smaller(1, 2)}")
To-do: sleep
Knowledge: 0
smaller(1, 2): 1

Использование словарей в качестве замены условных блоков

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

def win():
    print("You won!")

def lose():
    print("You lost!")

did_win = 1

# Using a conditional block
if did_win == 1:
    win()
else:
    lose()

# Using a dictionary instead of a conditional block
mapping = {1: win, 0: lose}

mapping[did_win]()

Выполнение резервного условия в цикле

else в цикле for выполняется сразу после завершения цикла. Я лично использую этот трюк в ситуации, когда требуется резервный механизм.

for num in range(1, 11):
    if num % 2 == 0:
        print(f"{num} is an even number")
else:
    print(f"We've reached {num} (the end of the loop)!")
2 is an even number
4 is an even number
6 is an even number
8 is an even number
10 is an even number
We've reached 10 (the end of the loop)!

Использование лямбда-функции для условного цикла

Можно выполнить условный цикл без использования операторов if и else, используя filterfalse из itertools. Этот метод принимает логическую функцию, которая сообщает, какие элементы не следует учитывать во время цикла. Это означает, что мы сохраняем только значения, которые не удовлетворяют условию внутри этого цикла.

from itertools import filterfalse

nums = list(range(1, 10))

no_even_nums = lambda x: x % 2 == 0

for num in filterfalse(no_even_nums, nums):
    print(f"{num} is an odd number")
1 is an odd number
3 is an odd number
5 is an odd number
7 is an odd number
9 is an odd number

Определение времени выполнения с помощью диспетчера контекста

Мы можем настроить диспетчер контекста в Python для определения времени выполнения определенной функции, фрагмента кода, сценария обучения и т. д. В примере, показанном ниже, мы моделируем процесс, завершение которого занимает примерно 0,25 секунды.

from contextlib import contextmanager
import time

@contextmanager
def timer():
    # Code executed inside the with block
    start = time.time()
    
    yield
    # Code executed outside the with block
    end = time.time()
    
    # Print the time elapsed
    print('Code block executed in {:.2f}s'.format(end - start))

with timer():
    time.sleep(0.25) # Simulate a slow running process
Code block executed in 0.25s

Обработка ошибок с помощью утверждений

Мы можем создавать собственные сообщения об ошибках, используя операторы assert. Передайте текст или сообщение об ошибке после утверждения, которое будет отображаться в случае сбоя утверждения. В приведенном ниже примере мы заявили, что допустимое количество входов — два. Однако мы пытаемся предоставить три входных параметра, которые помечают утверждение о выдаче сообщения об ошибке. Этот метод особенно полезен при обработке большого количества данных или при отладке и отслеживании логики очень длинного сценария.

num_of_inputs = 2
inputs = [0] * num_of_inputs + [1]

assert len(inputs) == num_of_inputs, "The number of inputs is not correct."
    assert len(inputs) == num_of_inputs, "The number of inputs is not correct."
AssertionError: The number of inputs is not correct.

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

Спасибо за чтение. Надеюсь, этот пост стоил вашего времени.