19 советов для улучшения вашего синтаксиса в Python
19 советов для улучшения вашего синтаксиса в Python
Заставить функцию работать – это одно. Другое дело – реализовать это с помощью точного и элегантного кода.
Как упоминалось в “The Zen of Python”: “красивое лучше, чем уродливое”. Хороший язык программирования, такой как Python, всегда предоставит соответствующий синтаксический сахар, который поможет разработчикам легко писать элегантный код.
В этой статье освещаются 19 важнейших синтаксических ошибок в Python. Путь к мастерству предполагает их понимание и умелое использование.
1. Операторы Объединения: Самый Элегантный Способ Объединения словарей Python
В Python существует множество подходов к объединению нескольких словарей, но ни один из них нельзя было назвать элегантным до тех пор, пока не был выпущен Python 3.9.
Например, как мы могли объединить следующие три словаря до Python 3.9?
Одним из методов является использование циклов for:
cities_us = {'New York City': 'US', 'Los Angeles': 'US'}
cities_uk = {'London': 'UK', 'Birmingham': 'UK'}
cities_jp = {'Tokyo': 'JP'}
cities = {}
for city_dict in [cities_us, cities_uk, cities_jp]:
for city, country in city_dict.items():
cities[city] = country
print(cities)
# {'New York City': 'US', 'Los Angeles': 'US', 'London': 'UK', 'Birmingham': 'UK', 'Tokyo': 'JP'}
Это работает, но данный способ далеко не элегантен.
В Python 3.9 были введены операторы объединения, которые сделали задачи объединения очень простыми:
cities_us = {'New York City': 'US', 'Los Angeles': 'US'}
cities_uk = {'London': 'UK', 'Birmingham': 'UK'}
cities_jp = {'Tokyo': 'JP'}
cities = cities_us | cities_uk | cities_jp
print(cities)
# {'New York City': 'US', 'Los Angeles': 'US', 'London': 'UK', 'Birmingham': 'UK', 'Tokyo': 'JP'}
Как показано в приведённой выше программе, мы можем просто использовать несколько символов вертикальной черты, так называемых операторов объединения в данном контексте, чтобы объединить столько словарей Python, сколько захотим.
Возможно ли выполнить сортировку слиянием с помощью операторов объединения?
cities_us = {'New York City': 'US', 'Los Angeles': 'US'}
cities_uk = {'London': 'UK', 'Birmingham': 'UK'}
cities_jp = {'Tokyo': 'JP'}
cities_us |= cities_uk | cities_jp
print(cities_us)
# {'New York City': 'US', 'Los Angeles': 'US', 'London': 'UK', 'Birmingham': 'UK', 'Tokyo': 'JP'}
Конечно, просто переместите операторы объединения слева от знака равенства, как показано в приведённом выше коде.
2. Подсказки по вводу: Сделайте ваши программы на Python безопасными для ввода
Динамическая типизация, которая означает определение типа переменной во время выполнения, является ключевой функцией, делающей Python гибким и удобным. Однако это также может привести к скрытым ошибкам, если переменные введены неправильно.
Чтобы решить эту проблему, Python внедрил функцию подсказки при вводе текста в версии 3.5. Она обеспечивает способ аннотирования типов переменных в коде, а современная среда IDE может обнаруживать ошибки типов на ранней стадии в процессе разработки.
Например, если мы определим переменную как целое число, но изменим её на строку следующим образом, IDE (в данном случае PyCharm) выделит для нас ошибочный код:
Помимо примитивных типов, существуют также некоторые продвинутые приёмы подсказок.
Например, в Python принято определять константы, используя все заглавные буквы.
DATABASE = 'MySQL'
Однако это всего лишь соглашение, и никто не может помешать вам присвоить новые значения этой константе.
Чтобы улучшить это, мы можем использовать подсказку типа Final
, которая указывает, что переменная предназначена для постоянного значения и не должна быть переназначена:
from typing import Final
DATABASE: Final = "MySQL"
Если мы действительно изменим константу, IDE наверняка напомнит нам об этом:
3. F-строки: Подход к форматированию строк на Pythonic
Python поддерживает несколько различных методов форматирования строк, таких как форматирование в стиле C с использованием символов %, встроенная функция format() и f-строки.
Если вы всё ещё не используете более старые версии, чем Python 3.6, f-строки, безусловно, являются наиболее удобным способом форматирования строк, потому что они могут выполнять все задачи форматирования с минимумом кода и даже запускать выражения внутри строк.
from datetime import datetime
today = datetime.today()
print(f"Today is {today}")
# Today is 2023-03-22 21:52:29.623619
print(f"Today is {today:%B %d, %Y}")
# Today is March 22, 2023
print(f"Today is {today:%m-%d-%Y}")
# Today is 03-22-2023
Как показано в приведённом выше коде, есть только две вещи, которые нужно сделать для использования f-строк:
- Добавить букву “f” перед строкой, чтобы указать, что это f-строка.
- Использовать фигурные скобки с именем переменной и необязательный спецификатор формата внутри строки (
{variable_name:format}
), чтобы интерполировать значение переменной в определённом формате.
“Простое лучше сложного”. f-строки являются хорошим отражением этой цитаты из “The Zen of Python”.
Более того, мы можем напрямую выполнить выражение внутри f-строки:
from datetime import datetime
print(f"Today is {datetime.today()}")
# Today is 2023-03-22 22:00:32.405462
4. Используйте многоточие в качестве заполнителя для ненаписанного кода
В Python мы обычно помещаем ключевое слово pass
в качестве заполнителя для ненаписанного кода. Но мы также можем использовать многоточие для этой цели.
def write_an_article():
...
class Author:
...
Гвидо ван Россум, отец Python, добавил этот синтаксический сахар в Python, потому что ему он показался ему милым.
5. Декораторы в Python: Способ разделения задач
Идея декораторов Python состоит в том, чтобы позволить разработчику добавлять новые функциональные возможности к существующему объекту без изменения его исходной логики.
Мы можем сами определить декораторов. А также есть множество замечательных встроенных декораторов, готовых к использованию.
Например, статические методы в классе Python не привязаны к экземпляру или классу. Они включены в класс просто потому, что они логически принадлежат ему.
Чтобы определить статический метод, нам просто нужно использовать декоратор @staticmethod
следующим образом:
class Student:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
self.nickname = None
def set_nickname(self, name):
self.nickname = name
@staticmethod
def suitable_age(age):
return 6 <= age <= 70
print(Student.suitable_age(99)) # False
print(Student.suitable_age(27)) # True
print(Student('yang', 'zhou').suitable_age(27)) # True
6. Списковое включение: Создайте список в одной строке кода
Python известен своей лаконичностью, которая в значительной степени объясняется его хорошо продуманным синтаксисом.
Со списковым включением мы можем поместить циклы for и условия if в одну строку кода для создания списка на Python:
Genius = ["Yang", "Tom", "Jerry", "Jack", "tom", "yang"]
L1 = [name for name in Genius if name.startswith('Y')]
L2 = [name for name in Genius if name.startswith('Y') or len(name) < 4]
L3 = [name for name in Genius if len(name) < 4 and name.islower()]
print(L1, L2, L3)
# ['Yang'] ['Yang', 'Tom', 'tom'] ['tom']
Кроме того, в Python также есть понимание множества, словаря и генератора. Их синтаксис аналогичен пониманию списка.
Например, следующая программа генерирует словарь на основе определённых условий:
Entrepreneurs = ["Yang", "Mark", "steve", "jack", "tom"]
D1 = {id: name for id, name in enumerate(Entrepreneurs) if name[0].isupper()}
print(D1)
# {0: 'Yang', 1: 'Mark'}
7. Лямбда-функции для определения небольших анонимных функций
Лямбда-функция, называемая анонимной функцией, представляет собой метод, позволяющий легко определить небольшую функцию в Python, чтобы сделать ваш код аккуратнее и короче.
Распространённым применением лямбда-функций является их использование для определения метода сравнения для встроенной функции sort()
:
leaders = ["Warren Buffett", "Yang Zhou", "Tim Cook", "Elon Musk"]
leaders.sort(key=lambda x: len(x))
print(leaders)
# ['Tim Cook', 'Yang Zhou', 'Elon Musk', 'Warren Buffett']
В приведённом выше примере лямбда-функция, которая принимает переменную и возвращает её длину, определена для использования в качестве метода сравнения при сортировке списка. Конечно, мы можем написать здесь полную функцию обычным способом. Но учитывая, что эта функция очень проста, записать её как лямбда-функцию определённо короче и аккуратнее.
8. Тернарный оператор: Поместите If и Else в одну строку кода
Многие языки программирования имеют тернарные операторы. Синтаксис Python для этого просто помещает if
и else
в одну строку:
short_one = a if len(a) < len(b) else b
Если мы реализуем ту же логику, что и выше, без тернарного оператора, потребуется несколько строк кода:
short_one = ''
if len(a) < len(b):
short_one=a
else:
short_one=b
9. Используйте метод “Enumerate” Для элегантного перебора списков
В некоторых случаях нам необходимо использовать как индекс, так и значения элементов в списке при его повторении.
Классический подход в стиле C для этого будет выглядеть следующим образом:
for (int i = 0; i < len_of_list; i++) {
printf("%d %s\n", i, my_list[i]);
}
Мы можем написать подобную логику на Python, но my_list[i]
кажется немного неуместным, особенно когда нам нужно вызывать значение элемента много раз.
Реальный питоновский способ сделать это – использовать функцию enumerate()
для получения как индекса, так и значений напрямую:
leaders = ["Warren", "Yang", "Tim", "Elon"]
for i,v in enumerate(leaders):
print(i, v)
# 0 Warren
# 1 Yang
# 2 Tim
# 3 Elon
10. Контекстный менеджер: Автоматическое закрытие ресурсов
Как мы знаем, после того, как файл был открыт и обработан, важно быстро закрыть его, чтобы освободить ресурсы памяти. Пренебрежение этим может привести к утечке памяти или даже к сбою нашей системы.
f = open("test.txt", 'w')
f.write("Hi,Yang!")
# some logic here
f.close()
Обрабатывать файлы на Python довольно просто. Как показывает приведённый выше код, нам просто нужно всегда помнить о вызове метода f.close()
, чтобы освободить память.
Однако, об этом можно забыть, когда программа становится всё более сложной и объёмной. Вот почему Python предоставляет синтаксический способ использования менеджера контекста.
with open("test.txt", 'w') as f:
f.write("Hi, Yang!")
Как показано выше, оператор “with” является ключевым для контекстных менеджеров Python. Пока мы открываем файл через него и обрабатываем файл под ним, файл будет автоматически закрыт после обработки.
11. Необычные приёмы нарезки списков на Python
Получение части элементов из списка является распространённым требованием. В Python оператор slice
состоит из трёх компонентов:
a_list[start:end:step]
- “start”: начальный индекс (значение по умолчанию равно 0).
- “end”: конечный индекс (значение по умолчанию – длина списка).
- “step”: определяет размер шага при итерациях по списку (значение по умолчанию равно 1).
Исходя из этого, есть несколько приёмов, которые могут сделать наш код более аккуратным.
Переверните список с помощью метода нарезки
Поскольку операторы среза могут быть отрицательными числами (-1 – последний элемент и так далее), мы можем использовать эту функцию для изменения списка таким образом:
a = [1,2,3,4]
print(a[::-1])
# [4, 3, 2, 1]
Получите небольшую копию списка
>>> a = [1, 2, 3, 4, 5, 6]
>>> b = a[:]
>>> b[0]=100
>>> b
[100, 2, 3, 4, 5, 6]
>>> a
[1, 2, 3, 4, 5, 6]
B=a[:]
отличается от b=a
, потому что он присваивает копию a
, а не саму a
. Таким образом, изменения в b
вообще не повлияют на a
, как показано выше.
12. Моржовый оператор: назначения в выражениях
Моржовый оператор, также известный как оператор выражения присваивания, был введён в Python 3.8 и представлен символом :=
.
Он используется для присвоения значений переменным внутри выражения, а не для присвоения их по отдельности.
Например, рассмотрим следующий код:
while (line := input()) != "stop":
print(line)
В этом коде моржовый оператор используется для присвоения значения пользовательского ввода переменной line
, одновременно проверяя, был ли остановлен ввод. Цикл while будет продолжать выполняться до тех пор, пока пользовательский ввод не будет “остановлен”.
Кстати, моржовый оператор, :=
, получил свое милое название из-за глаз и клыков моржа:
13. Непрерывные Сравнения: Более Естественный Способ Записи Условий If
В таких языках, как Java или C, иногда вам нужно написать, if-условия, подобные этому:
if (a > 1 && a < 10){
//do somthing
}
Однако вы не сможете написать это так элегантно, как показано ниже, если вы не используете Python:
if 1 < a < 10:
...
Да, Python позволяет нам писать непрерывные сравнения. Это заставляет наш код казаться таким же естественным, как в математике.
14. Функция Zip: Легко объединяйте несколько повторяющихся файлов
В Python есть встроенная функция zip()
, которая принимает два или более итерируемых объекта в качестве аргументов и возвращает итератор, который объединяет элементы.
Например, с помощью функции zip()
следующий код объединяет 3 списка в один без каких-либо циклов:
id = [1, 2, 3, 4]
leaders = ['Elon Mask', 'Tim Cook', 'Bill Gates', 'Yang Zhou']
sex = ['male', 'male', 'male', 'male']
record = zip(id, leaders, sex)
print(list(record))
# [(1, 'Elon Mask', 'male'), (2, 'Tim Cook', 'male'), (3, 'Bill Gates', 'male'), (4, 'Yang Zhou', 'male')]
15. Прямая замена двух переменных
Замена двух переменных обычно является первой программой, которую новичок напишет после вывода “Hello world!”.
Классическому способу сделать это на многих языках программирования требуется временная переменная для хранения значения одной из переменных.
Например, вы можете поменять местами два целых числа в Java следующим образом:
int a = 5;
int b = 10;
int temp = a;
a = b;
b = temp;
System.out.println("a = " + a); // Output: a = 10
System.out.println("b = " + b); // Output: b = 5
В Python синтаксис настолько интуитивно понятен и элегантен:
a = 10
b = 5
a, b = b, a
print(a, b)
# 5 10
16. Приёмы деструктуризации
Деструктуризация в Python – это способ присвоения элементов итератора или словаря отдельным переменным. Он позволяет вам писать более короткий и читаемый код, избегая необходимости обращаться к отдельным элементам с помощью индексов или ключей.
person = {'name': 'Yang', 'age': 30, 'location': 'Mars'}
name, age, loc = person.values()
print(name, age, loc)
# Yang 30 Mars
Как показано в примере выше, мы можем напрямую присвоить значения словаря 3 отдельным переменным в одной строке кода.
Однако, если в левой части есть только две переменные, как получать назначения?
Python предоставляет другой способ для этого:
person = {'name': 'Yang', 'age': 30, 'location': 'Mars'}
name, *others = person.values()
print(name, others)
# Yang [30, 'Mars']
Как показано выше, мы можем просто добавить звёздочку перед переменной, чтобы позволить ей получать все остальные переменные от person.values()
.
Просто и элегантно, не правда ли?
17. Распаковка повторяющихся объектов со звездочками
Помимо деструктурирующих назначений, звездочки в Python также являются ключами для итеративной распаковки.
A = [1, 2, 3]
B = (4, 5, 6)
C = {7, 8, 9}
L = [*A, *B, *C]
print(L)
# [1, 2, 3, 4, 5, 6, 8, 9, 7]
Как показано выше, самый простой способ объединить список, множество и кортеж в один список – это распаковать их с помощью звёздочек в новом списке.
18. Функции Any() и All()
В некоторых случаях нам нужно проверить, являются ли какие-либо или все элементы (такие как список, кортеж или множество) истинными.
Конечно, мы можем использовать циклы for, чтобы проверять их один за другим. Но Python предоставляет две встроенные функции any()
и all()
для упрощения кода этих двух операций.
Например, следующая программа использует all()
, чтобы определить, являются ли все элементы списка нечётными числами:
my_list = [3, 5, 7, 8, 11]
all_odd = all(num % 2 == 1 for num in my_list)
print(all_odd)
# False
Следующий код использует функцию any()
, чтобы проверить, существует ли лидер, имя которого начинается на “Y”:
leaders = ['Yang', 'Elon', 'Sam', 'Tim']
starts_with_Y = any(name.startswith('Y') for name in leaders)
print(starts_with_Y)
# True
19. Подчёркивания в цифрах
Подсчитать, сколько нулей в большом числе – это головная боль.
К счастью, Python позволяет включать символы подчёркивания в числа для улучшения удобочитаемости.
Например, вместо того, чтобы писать 10000000000
, мы можем написать 10_000_000_000
, что будет намного удобнее.
Спасибо за чтение. ❤️