- PVSM.RU - https://www.pvsm.ru -
Привет! Предлагаю Вашему вниманию перевод статьи Good and Bad Practices of Coding in Python [1] автора Duomly.
Python – высокоуровневый язык программирования, акцентирующий внимание на удобочитаемости. Он разрабатывается, поддерживается и часто используется в соответствии с The Zen of Python или PEP 20.
В этой статье показано несколько примеров хороших и плохих методов кодинга в Python, с которыми вы, вероятно, столкнетесь.
Упаковка и распаковка — мощные инструменты Python. Вы можете использовать распаковку для присваивания значений переменным:
>>> a, b = 2, 'my-string'
>>> a
2
>>> b
'my-string'
Вы можете использовать это для написания, возможно, самого компактного кода, меняющего значения переменных местами
>>> a, b = b, a
>>> a
'my-string'
>>> b
2
Это потрясающе!
Распаковка также может быть использована для присвоения значения нескольким переменным в более сложных случаях. Например, Вы можете написать так:
>>> x = (1, 2, 4, 8, 16)
>>> a = x[0]
>>> b = x[1]
>>> c = x[2]
>>> d = x[3]
>>> e = x[4]
>>> a, b, c, d, e
(1, 2, 4, 8, 16)
Но вместо этого Вы также можете воспользоваться более лаконичным и, возможно, более читабельным способом:
>>> a, b, c, d, e = x
>>> a, b, c, d, e
(1, 2, 4, 8, 16)
Это круто, правда? Но можно написать еще круче:
>>> a, *y, e = x
>>> a, e, y
(1, 16, [2, 4, 8])
Фишка в том, что переменная с * собирает значения, не назначенные другим переменным.
Python позволяет использовать цепочки операторов сравнения. Таким образом, Вам не нужно проверять, являются ли два или более сравнения истинными:
>>> x = 4
>>> x >= 2 and x <= 8
True
Вместо этого Вы можете использовать более компактную форму написания:
>>> 2 <= x <= 8
True
>>> 2 <= x <= 3
False
Python также поддерживает присваивание значений переменным в виде цепочки. Итак, если Вы хотите присвоить одно и то же значение нескольким переменным одновременно, Вы можете сделать это простым способом:
>>> x = 2
>>> y = 2
>>> z = 2
Более компактный способ — использовать распаковку:
>>> x, y, z = 2, 2, 2
Тем не менее, все выглядит ещё круче, если использовать присвоение значения цепочкой:
>>> x = y = z = 2
>>> x, y, z
(2, 2, 2)
Будьте осторожны, когда значения разные! Все переменные ссылаются на одно и то же значение.
None не является уникальным объектом в Python. Он имеет аналоги, например, null в C-подобных языках.
Можно проверить, ссылается ли переменная на None с помощью операторов сравнения == и !=:
>>> x, y = 2, None
>>> x == None
False
>>> y == None
True
>>> x != None
True
>>> y != None
False
Однако, предпочтительнее использование is и is not:
>>> x is None
False
>>> y is None
True
>>> x is not None
True
>>> y is not None
False
Кроме того, лучше использовать конструкцию x is not None, а не менее читабельную альтернативу (x is None).
Вы можете реализовать циклы в Python несколькими способами. Python предлагает несколько встроенных классов для упрощения их реализации.
Почти всегда Вы можете использовать диапазон, чтобы получить цикл, который выдает целые числа:
>>> x = [1, 2, 4, 8, 16]
>>> for i in range(len(x)):
... print(x[i])
...
1
2
4
8
16
Однако для этого есть лучший способ:
>>> for item in x:
... print(item)
...
1
2
4
8
16
Но что, если Вы хотите запустить цикл в обратном порядке? Конечно, снова можно использовать диапазон:
>>> for i in range(len(x)-1, -1, -1):
... print(x[i])
...
16
8
4
2
1
Но «перевернуть» последовательность – более компактный способ:
>>> for item in x[::-1]:
... print(item)
...
16
8
4
2
1
Pythonic способ заключается в использовании обратной последовательности, чтобы получить цикл, который будет возвращать элементы последовательности в обратном порядке:
>>> for item in reversed(x):
... print(item)
...
16
8
4
2
1
Иногда необходимы как элементы последовательности, так и соответствующие им индексы:
>>> for i in range(len(x)):
... print(i, x[i])
...
0 1
1 2
2 4
3 8
4 16
Лучше использовать перечисление, чтобы получить другой цикл, который возвращает значения индексов и элементов:
>>> for i, item in enumerate(x):
... print(i, item)
...
0 1
1 2
2 4
3 8
4 16
Это круто. Но что, если необходимо перебрать две или более последовательности? Конечно, можно снова использовать диапазон:
>>> y = 'abcde'
>>> for i in range(len(x)):
... print(x[i], y[i])
...
1 a
2 b
4 c
8 d
16 e
В этом случае Python также предлагает лучший способ решения. Вы можете применить zip:
>>> for item in zip(x, y):
... print(item)
...
(1, 'a')
(2, 'b')
(4, 'c')
(8, 'd')
(16, 'e')
Можно также скомбинировать этот метод с распаковкой:
>>> for x_item, y_item in zip(x, y):
... print(x_item, y_item)
...
1 a
2 b
4 c
8 d
16 e
Пожалуйста, имейте в виду, что диапазон может быть весьма полезным. Тем не менее, есть случаи (как, например, выше), где оптимальнее использовать альтернативы.
Перебор словаря дает его ключи:
>>> z = {'a': 0, 'b': 1}
>>> for k in z:
... print(k, z[k])
...
a 0
b 1
Однако вы можете применить метод .items () и получить ключи и соответствующие им значения:
>>> for k, v in z.items():
... print(k, v)
...
a 0
b 1
Можно также использовать методы .keys () и .values () для перебора ключей и значений соответственно.
Когда у Вас есть числовые данные, и нужно проверить, равны ли числа нулю, можно (но не всегда нужно) использовать операторы сравнения == и !=:
>>> x = (1, 2, 0, 3, 0, 4)
>>> for item in x:
... if item != 0:
... print(item)
...
1
2
3
4
Способ, предлагаемый Python, состоит в том, чтобы интерпретировать нуль как False, а все другие числа как True:
>>> bool(0)
False
>>> bool(-1), bool(1), bool(20), bool(28.4)
(True, True, True, True)
Имея это в виду, Вы можете использовать if item вместо if item! = 0:
>>> for item in x:
... if item:
... print(item)
...
1
2
3
4
Вы можете следовать той же логике и использовать if not item вместо if item == 0.
У Python очень гибкая система предоставления аргументов функциям и методам. Необязательные аргументы являются частью этого. Но будьте осторожны: Вы обычно не хотите использовать изменяемые необязательные аргументы. Рассмотрим следующий пример:
>>> def f(value, seq=[]):
... seq.append(value)
... return seq
На первый взгляд это выглядит так, если вы не укажете seq, f () добавляет value в пустой список и возвращает что-то вроде [value]:
>>> f(value=2)
[2]
Выглядит здорово, правда? Нет! Рассмотрим следующие примеры:
>>> f(value=4)
[2, 4]
>>> f(value=8)
[2, 4, 8]
>>> f(value=16)
[2, 4, 8, 16]
Удивлены? Если да, то не Вы одни.
Кажется, что каждый раз, когда вызывается функция, предоставляется один и тот же экземпляр необязательного аргумента (в данном случае, списка). Может быть, иногда это и будет то, что Вам нужно. Тем не менее, гораздо более вероятно, что Вам необходимо будет избежать это. Один из способов заключается в следующем:
>>> def f(value, seq=None):
... if seq is None:
... seq = []
... seq.append(value)
... return seq
Версия покомпактней:
>>> def f(value, seq=None):
... if not seq:
... seq = []
... seq.append(value)
... return seq
Теперь мы получаем другой вывод:
>>> f(value=2)
[2]
>>> f(value=4)
[4]
>>> f(value=8)
[8]
>>> f(value=16)
[16]
В большинстве случаев это то, что нужно.
Python позволяет определять методы getter и setter так же, как C ++ и Java:
>>> class C:
... def get_x(self):
... return self.__x
... def set_x(self, value):
... self.__x = value
Вот как Вы можете использовать их:
>>> c = C()
>>> c.set_x(2)
>>> c.get_x()
2
В некоторых случаях это лучший способ. Однако часто лучше использовать свойства, особенно в простых случаях:
>>> class C:
... @property
... def x(self):
... return self.__x
... @x.setter
... def x(self, value):
... self.__x = value
Свойства считаются более Pythonic, чем классические геттеры и сеттеры. Вы можете использовать их так же, как в C#, то есть так же, как обычные атрибуты данных:
>>> c = C()
>>> c.x = 2
>>> c.x
2
Так что, в общем, лучше использовать свойства, когда это возможно.
В Python отсутствуют как таковые private члены класса. Однако, если в начале названия элемента написать (_), то доступ к его изменению за пределами класса будет запрещен.
Например, рассмотрим код:
>>> class C:
... def __init__(self, *args):
... self.x, self._y, self.__z = args
...
>>> c = C(1, 2, 4)
Экземпляры класса C имеют три элемента данных: .x, .y и ._Cz. Если имя участника начинается с двойного подчеркивания (dunder), оно становится измененным. Вот почему вместо ._z элемент ._Cz.
Теперь можно доступ или изменить напрямую .x:
>>> c.x # OK
1
Вы также можете получить доступ или изменить ._y вне его класса, но это считается моветоном:
>>> c._y # Possible, but a bad practice!
2
Вы не можете получить доступ к .z, потому что переменная изменена, но вы можете получить доступ или изменить ._Cz:
>>> c.__z # Error!
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'C' object has no attribute '__z'
>>> c._C__z # Possible, but even worse!
4
>>>
Вы должны избегать этого. Автор класса, вероятно, начинает имена с подчеркивания, чтобы подчеркнуть то, что лучше не использовать данный элемент вне его класса.
Иногда требуется написать код для правильного управления ресурсами. Это часто бывает при работе с файлами, подключениями к базам данных или другими объектами с неуправляемыми ресурсами. Например, вы можете открыть файл и обработать его:
>>> my_file = open('filename.csv', 'w')
>>> # do something with `my_file`
Чтобы правильно управлять памятью, Вам необходимо закрыть этот файл после завершения работы:
>>> my_file = open('filename.csv', 'w')
>>> # do something with `my_file and`
>>> my_file.close()
Делать это таким способом лучше, чем не делать вовсе. Но что, если во время обработки Вашего файла возникает исключение? Тогда my_file.close () никогда не выполняется. Можно справиться с этим с помощью обработки исключений или с помощью контекстных менеджеров. Второй способ означает, что вы помещаете свой код в блок with:
>>> with open('filename.csv', 'w') as my_file:
... # do something with `my_file`
Использование блока with означает, что специальные методы .enter () и .exit () вызываются даже в случаях исключений. Эти методы должны заботиться о ресурсах.
Вы можете добиться особенно надежных конструкций, комбинируя контекстные менеджеры и обработку исключений.
Код Python должен быть элегантным, лаконичным и читабельным.
Основной ресурс на тему того, как написать красивый код Python, — это Style Guide for Python Code или PEP 8. Вам стоит прочитать его, если хотите писать код на Python.
Эта статья дает несколько советов о том, как написать более компактный, читабельный код. Короче говоря, она показывает, как сделать код более Pythonic. Кроме того, PEP 8 предоставляет Style Guide for Python Code, а PEP 20 представляет принципы языка Python.
Наслаждайтесь написанием полезного и красивого кода!
Спасибо за чтение.
Автор: sovesttut
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/338569
Ссылки в тексте:
[1] Good and Bad Practices of Coding in Python: https://dev.to/duomly/the-best-practices-of-coding-in-python-and-what-to-avoid-3c65
[2] Источник: https://habr.com/ru/post/478380/?utm_campaign=478380&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.