20 рекомендаций, которые необходимо соблюдать разработчикам Python

В статье содержится список из 20 рекомендаций, которым должны следовать все программисты Python.

Каждое руководство дополнительно поддерживается подходящим фрагментом кода.

1. Используйте f-строки вместо строк C-style и str.format.

blog_number = 1
my_blog = f'This is my blog number: {blog_number}'
print(my_blog)
This will return This is my blog number: 1

2. Укажите кодировку при чтении текста из внешних источников.

import io
file = io.open("my_file", mode="r", encoding="utf-8")

3. Используйте оператор with или try / finally, чтобы обеспечить быструю и надежную очистку локального ресурса после использования.

file = open('my_file', 'w')
try:
 file.write('this is a fintechexplained blog')
finally:
 file.close()
# using with statement
with open('my_file', 'w') as file:
file.write('this is a fintechexplained blog')

4. Вывести исключения из Exception, а не из BaseException.

class MyNewException(Exception):
   pass
raise MyNewException

5. Для всех предложений try / except ограничьте предложение try абсолютным минимальным объемом кода.

try:
  #critical code section
except ValueError as err:
  #handle error

6. Будьте последовательны в операторах возврата. Либо все достижимые выражения возврата функции должны возвращать оператор, либо функция всегда должна возвращать None для всех ветвей функции.

def get_result(input):
 if input == 'a':
   return True
 elif input == 'b':
   return False
 
 #default case
 return False

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

7. Если нас не интересуют все предметы в коллекции, используйте звездочку, чтобы распаковать их.

items = ['a', 'b', 'c', 'd']
a, b, *others = items
print(others)
This will return c and d

8. Используйте nampedtuple для простых структур, которые делают стандартные структуры данных Python вложенными, если они используются.

from collections import namedtuple
Blog = namedtuple('Blog', [
   'name',
   'author',
])
my_blog = Blog('pro python', 'Farhad Malik ')
print(my_blog.name)
This will print pro python

Для сложных структур с состояниями вместо этого создайте класс.

9. Не добавляйте в функции изменяемое значение параметра по умолчанию. Значение аргумента по умолчанию оценивается только один раз при загрузке функции, а не при каждом вызове функции.

Обратите внимание, как параметр some_arg изменяется при каждом вызове функции.

def my_func(input, some_arg = []):
    some_arg.extend(input)
    print(some_arg)
    
my_func(['a'])
my_func(['a', 'b'])
The function will now print a, a, b
Calling my_func(['this is new']) will print ['a', 'a', 'b', 'this is new']

Вместо этого установите значение None и проверьте, равен ли аргумент (some_arg) None. Если это None, инициализируйте его в функции со значением по умолчанию - пустым списком.

10. Используйте декоратор оберток из встроенного модуля functools, когда вы определяете свои собственные декораторы. Гарантирует, что функция wrapper получает атрибуты обернутой функции.

#Problem
def some_decorator(some_function):
    def wrapper():
        some_function()
    return wrapper


@some_decorator
def print_my_blog():
    print("this is my blog")


print(print_my_blog.__name__)
# This will print wrapper instead of print_my_blog
#Solution
from functools import wraps
def some_decorator(some_function):
    @wraps(some_function)
    def wrapper():
        some_function()
    return wrapper


@some_decorator
def print_my_blog():
    print("this is my blog")


print(print_my_blog.__name__)
# This will print print_my_blog

Если вы хотите понять Python от начала до конца, я настоятельно рекомендую прочитать эту статью:



11. Используйте оператор моржа, чтобы исключить повторы в понимании списка / словаря.

collection = [
    {"name": "farhad", "address": "address1"},
    {"name": "malik", "address": "address2"},
]

for item in collection:
    if name := item.get("name"):
        print(f'the name is {name}')
This will print
the name is farhad
the name is malik

12. Когда ваши коллекции больше по размеру, верните генераторы.

def non_ending_collection():
    val = 'never ending val'
    while True:
        yield val

13. Избегайте использования встроенных вложенных словарей Python для представления сложных объектов. Вместо этого создайте свои собственные пользовательские классы.

#Instead of a nested dictionary, create a custom class
custom_obj = {
    "child": {
        "child": {
            "child": {
                "child": None,
                "some_property": "some value"
            },
            "some_property": "some value"
        },
        "some_property": "some value"
    },
    "some_property": "some value"
}
# Create a class
class complex_class:
    def __init__(self, child):
        self.child = child
        self.some_property = 'some value'


object = complex_class(complex_class(complex_class(complex_class(None))))

14. Создавайте функции вместо классов для очень простых структур. Если необходимо поддерживать состояние, используйте метод __call__.

class MyComplexFunction:
    def __init__(self):
        self.input = None
        pass

    def __call__(self, input):
        self.input = input


func = MyComplexFunction()
func('can you see this?') # calls __call__

#this will print can you see this?
print(func.input)

15. Используйте @classmethod, чтобы определить альтернативные конструкторы для вашего класса. Помните, Python поддерживает только один конструктор для каждого класса.

class Blog:
    def __init__(self):
        print('created blog')
    
    @classmethod
    def create_with_name(self, name):
        print(f'created blog with name {name}')

blog = Blog()
blog = Blog.create_with_name('new blog')
This will print 
can you see this?
created blog
created blog with name new blog

16. Если нам нужно особое поведение для свойства, используйте декоратор @property для реализации пользовательских методов получения и установки.

class Blog:
    def __init__(self):
        self.__special_id__= ''

    @property
    def special_id(self):
        return self.__special_id__

    @special_id.setter
    def special_id(self, value):
        self.__special_id__= f'123 {value}'

blog = Blog()
blog.special_id = 'this is a blog'
print(blog.special_id)
This will print
123 this is a blog

17. Если вас беспокоит утечка памяти, используйте WeakKeyDictionary вместо экземпляра словаря, чтобы предотвратить утечку памяти. WeakKeyDictionary собирается сборщиком мусора, чтобы освободить память.

import weakref 
my_dict = weakref.WeakKeyDictionary()
my_dict['a'] = some_custom_obj

18. Избегайте запуска нескольких процессов Python, если на вашем компьютере один ЦП / ядро, и избегайте использования потоков, если узкие места в вашем коде не связаны с операциями ввода-вывода.

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

Это длинная тема, и я написал статью, чтобы объяснить концепции, которые я настоятельно рекомендую всем программистам Python:



19. Используйте метаклассы с умом.

Мета-классы чрезвычайно мощны и могут значительно расширить ваше приложение. Я написал статью, в которой объясняется, что такое метапрограммирование в Python, и я настоятельно рекомендую ее каждому программисту на Python:



20. Используйте декораторы классов, чтобы украсить класс. Декораторы классов могут создать новый экземпляр или изменить внедренный экземпляр класса.

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

Есть несколько способов реализовать эту функциональность, но приведенный ниже пример предназначен только для иллюстративных целей. Мы собираемся добавить поведение во все наши объекты. Все наши классы требуют заполнения атрибута time_added:

import datetime
def my_class_pattern(cls):

    class InnerClass(cls):
        def __init__(self, *args, **kargs):
            super(InnerClass, self).__init__(*args, **kargs)
            self.time_added = datetime.datetime.now()
    return InnerClass

@my_class_pattern
class Blog:
    def __init__(self):
        print('created blog')


blog = Blog()
print(blog.time_added)
# This will print
created blog
2020-12-30 11:52:03.359089

Резюме

В этой статье представлены 20 наиболее рекомендуемых рекомендаций, которым должны следовать профессиональные программисты Python.