Большинство питонистов не раз слышали о таких правилах как «функции должны быть глаголами» или «не наследуйтесь явно от object в Python 3». В этой статье мы рассмотрим не такие банальные, но полезные правила чистого кода в Python.

Необязательное вступление

Идея статьи возникла при выполнении Code review одного проекта. В тот момент я понял что пора объединить и структурировать накопленные правила чистого кода.

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

Функции

Правило №1 - Имя начинается с нижнего подчёркивания, если функция используется только в том модуле, в котором она создана

Такой подход даёт понять, что функция не используется и не должна использоваться в других файлах. По крайней мере, на уровне соглашений.

Например в проекте есть модули «a.py», «b.py» и «c.py». Функция get_user_name создана в модуле «a.py». Используется она тоже только в нём. Тогда её следует переименовать в _get_user_name.

Правило №2 - Примеры использования функции в docstrings пишутся в виде doctest

Напишем такую функцию:

def get_sum(number_1: int, number_2: int) -> int:
    """Вернёт сумму двух чисел.

    Примеры:
    get_sum(0, 2) = 2
    get_sum(1, 2) = 3
    get_sum(3, 5) = 8

    """

    return number_1 + number_2


print(get_sum(10, 15))

Функция работает, но запустив код, мы никак не проверим примеры из docstring:

# Флаг «v» выводит дополнительные детали выполнения программы
$ python script.py -v
25

Исправим это с помощью модуля doctest:

from doctest import testmod


def get_sum(number_1: int, number_2: int) -> int:
    """Вернёт сумму двух чисел.

    >>> get_sum(0, 2)
    2
    >>> get_sum(1, 2)
    3
    >>> get_sum(3, 5)
    8

    """

    return number_1 + number_2


if __name__ == "__main__":
    print(get_sum(10, 15))

    testmod()

Теперь запустим программу:

$ python script.py -v
25
Trying:
    get_sum(0, 2)
Expecting:
    2
ok
Trying:
    get_sum(1, 2)
Expecting:
    3
ok
Trying:
    get_sum(3, 5)
Expecting:
    8
ok
1 items had no tests:
    __main__
1 items passed all tests:
   3 tests in __main__.get_sum
3 tests in 2 items.
3 passed and 0 failed.
Test passed.

Мы получили результат работы программы и результат выполнения тестов из docstring. Уберите флаг «v», если хотите вывести только результат работы программы:

$ python script.py
25

Правило №3 - У аргументов функции указан type hint

Взгляните на эту функцию:

def is_user_name_valid(user_name): pass

Какое значение нужно передать в переменную user_name? Строку с именем? Словарь с ФИО? Может ещё что-то? Скорее всего строку с именем, но для полной уверенности надо читать саму функцию. Type hint освобождает от этой траты времени:

def is_user_name_valid(user_name: str): pass

Плюсы использования type hint:

  1. Позволяет не думать над типом аргумента;

  2. Немного документирует код;

  3. Уменьшает число ошибок, связанных с типом аргумента;

  4. Облегчает разработку в некоторых IDE. Например PyCharm может ругаться на аргумент, который не соответствует type hint.

Type hint для аргументов по умолчанию

Для аргументов по умолчанию тоже можно задать type hint:

def is_user_name_valid(user_name: str = "admin"): pass

Особенно это полезно если аргумент может принимать значения разных типов:

# Для Python 3.10
def is_positive(number: int | float = 100): pass


# Для Python 3.9 и ниже
from typing import Union

def is_positive(number: Union[int, float] = 100): pass

Type hint для переменных

Для переменных тоже можно указать type hint. Но нет смысла это делать, если тип переменной и так понятен.

Плохо:

cat_name: str = "Tom"

Хорошо:

# settings.PAGE_SIZE может иметь значение разных типов, например str и int
page_size: int = settings.PAGE_SIZE

Правило №4 - У функции указан type hint возвращаемого значения

Type hint полезен не только для аргументов и переменных, но и для возвращаемого значения функции. За счёт него можно не заглядывать в тело функции, а сразу понять какой тип она вернёт.

from typing import Callable


def get_user_name() -> str: ...

def is_user_name_valid(user_name: str) -> bool: ...

def get_wrapped_function() -> Callable: ...

def run_tests() -> None: ...

У функции, которая возвращает другую функцию, указывается type hint Callable. У функции, которая ничего не возвращает, указывается type hint None.

Классы

Правило №5 - Приватные методы располагаются ниже магических и публичных

Допустим, есть такой кот класс:

class Cat:
    """Просто кот"""

    def __init__(self, name: str):
        self.name = name

    def ask_for_food(self) -> None:
        self.__say_meow()
        self.__say_meow()

    def __say_meow(self) -> None:
        print(f"{self.name} says meow")

Мы создаем его объект и вызываем публичный метод:

tom = Cat("Tom")
tom.ask_for_food()

Если человек захочет понять что делает метод ask_for_food, то он прочитает содержимое класса Cat в таком порядке:

  1. Прочитает метод __init__ и поймёт куда заносится имя "Tom";

  2. Прочитает метод ask_for_food и увидит в нём вызов метода __say_meow;

  3. Прочитает метод __say_meow.

Т.е. приватный пользовательский метод читается в последнюю очередь. Так всегда происходит со всеми не магическими private-методами, если в коде соблюдаются принципы ООП.

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

  1. __new__ (если такой метод используется в классе);

  2. __init__;

  3. Остальные магические методы;

  4. Public-методы;

  5. Protected-методы;

  6. Private-методы.

Переменные

Правило №6 - Названия переменных, в которых хранятся измеряемые данные, содержат единицу измерения

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

Плохо

cooking_time = 30
user_weight = 5

Лучше, но всё ещё плохо:

# Время в минутах
cooking_time = 30

# Вес в килограммах
user_weight = 5

Хорошо

cooking_time_in_minutes = 30
user_weight_in_kg = 5

Дополнительно об этом правиле можно прочитать в книге «Чистый код», глава 2, пункт «Имена должны передавать намерения программиста».

Правило №7 - Названия неиспользуемых переменных заменяются на нижнее подчёркивание

Напишем следующий код:

for i in range(10):
    print("Hello!")

Переменная i внутри цикла не используется. Заменим её на нижнее подчеркивание - традиционное обозначение неиспользуемых переменных:

for _ in range(10):
    print("Hello!")

С точки зрения Python мы поменяли имя переменной i на _. Работа программы от этого не изменилась. Но зато человек, который будет читать код, поймёт, что внутри цикла не используется итерационная переменная.

Это правило обычно применяется и при распаковке последовательностей:

# a = 1; _ = 2
a, _ = 1, 2

# a = 1; _ = [2, 3, 4]
a, *_ = (1, 2, 3, 4)
a, *_ = [1, 2, 3, 4]
a, *_ = {1, 2, 3, 4}
a, *_ = {1: '1', 2: '2', 3: '3', 4: '4'}

Т.е. значения 2, 3 и 4 мы использовать не собираемся, но сохранить их где-то надо.

Когда не следует использовать это правило

Не используйте это правило если пишите на Django, и в вашем коде есть функция gettext. Её принято заменять на нижнее подчёркивание. Хотя ошибки в коде не произойдет, но у программиста может возникнуть недопонимание:

from django.utils.translation import gettext as _


title = _("Интернет-магазин «Кошачий рай»")

# Программист: «Почему здесь исользуется функция gettext?»
for _ in range(10): # Цикл спокойно работает
    print(1)

Дополнительно об этом правиле читайте тут.

Числа

Правило №8 - Число разделяется нижним подчеркиванием через каждые 3 цифры

Для удобства пользователя, в большинстве приложений числа разделяются пробелом через каждые 3 цифры. Например, вместо 1000000 пишется 1 000 000. В Python тоже есть такая возможность, но вместо пробела используется нижнее подчеркивание.

Плохо

number_of_accounts = 1500

sum_in_rubles = 1234567890

Хорошо

number_of_accounts = 1_500

sum_in_rubles = 1_234_567_890

Дополнительно о правиле читайте в этой статье, в пункте «Example 5: Single underscore in numeric literals».

Правило №9 - Число пишется в виде формулы, если его можно так записать

Плюсы применения правила:

  1. Легче и быстрее понять, как появилось число;

  2. Легче и быстрее изменить число - надо просто поменять параметры формулы;

  3. Из кода удаляются «магические числа»;

  4. В коде становится меньше лишних комментариев.

Плохо:

flight_time_in_seconds = 10_800

Лучше, но всё ещё плохо:

# 60 секунд * 60 минут * 3
flight_time_in_seconds = 10_800

Хорошо:

flight_time_in_seconds = 60 * 60 * 3

Очень хорошо:

MIN_IN_SECONDS = 60
HOUR_IN_SECONDS = MIN_IN_SECONDS * 60

flight_time_in_seconds = HOUR_IN_SECONDS * 3

Идеально:

# Код файла constants.py
MIN_IN_SECONDS = 60
HOUR_IN_SECONDS = MIN_IN_SECONDS * 60

# Код файла script.py
from constants import HOUR_IN_SECONDS

flight_time_in_seconds = HOUR_IN_SECONDS * 3

Объём кода становится больше, но времени на осознание и, при необходимости, изменение переменной flight_time_in_seconds - меньше.

Ещё 2 статьи по правилам чистого кода

Во второй части статьи я расскажу про остальные правила. Также в ближайшее время планируется публикация по правилам чистого кода в Django-проектах.

Надеюсь, полученная информация принесла вам пользу. До скорых встреч)

Комментарии (44)


  1. Andrey_Solomatin
    31.10.2022 13:39
    +6

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

    Не магические приватные методы располагаются ниже магических и публичных

    Магические и приватные это как теплое и мягкое. Лучше "Не магические приватные методы" заменить на "Приватные методы"

    Может быть "правила" заменить на "рекомендации", по аналогии с PEP8: делайте так, если у вас нет веской причины делать по другому.

    Аннотации это хорошо, и в основном просто. В редких случаях приходиться постараться, чтобы они работали и проходили линтеры.

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


    1. OsnovaDT Автор
      31.10.2022 13:53
      +1

      Магические и приватные это как теплое и мягкое. Лучше "Не магические приватные методы" заменить на "Приватные методы"

      Согласен, заменил, спасибо.

      Может быть "правила" заменить на "рекомендации", по аналогии с PEP8

      Дело в том, что для меня это именно правила, и я всегда им следую, поэтому так и назвал. Возможно, кто-то тоже захочет какие-то из них сделать своими "правилами".

      На счет доктестов, я пока не смог настроить их в Django-проекте, запускающемся через Docker. Точнее не "не смог", а не нашел времени чтобы разобраться.


  1. mrkaban
    31.10.2022 13:52
    +4

    Правило №6 - слишком длинное имя (cooking_time_in_minutes) переменной получается. Я конечно понимаю, что сейчас все IDE умные и поддерживают автозавершение кода, но все таки... Майкл Доусон еще писал, что переменные должны быть лаконичными, то есть понятными и короткими, а не быть размером с небольшое предложение.

    Правило №7 - интересно, сам не догадался, возьму на вооружение.


    1. OsnovaDT Автор
      31.10.2022 13:58
      +1

      Правило №6 - слишком длинное имя

      Согласен что длинное, но не согласен что слишком. 23 символа по мне не так много, можно спокойно писать, не нарушая PEP. Из авторов я больше следую советам Роберта Мартина, а он, если не ошибаюсь, писал что не столь важна длина, сколько важная ясность названия


      1. mrkaban
        01.11.2022 05:10

        Имена переменных в 5 символов это зло, но и они не должны быть такими, будто бы ты в имени переменной хочешь рассказать как прошло твоё утро, помимо того зачем она вообще нужна.

        Логика в том, что длинные имена переменных без IDE не удобно писать и повышается риск опечатки, если ты торопишься и есть похожие имена. Сидишь после работы и дописываешь на голом энтузиазме программу, и так устал и бдительность усыплена, а тут еще и длинные похожие имена переменных, IDE предложила не то, а ты не до конца прочитал что она предложила. Имена ведь вполне могут быть похожие из-за некоторой схожести по назначению.

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


        1. OsnovaDT Автор
          01.11.2022 15:16

          длинные имена переменных без IDE не удобно писать

          Мне кажется сейчас абсолютно все пишут с помощью IDE.

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

          IDE предложила не то, а ты не до конца прочитал что она предложила

          Кстати в такой ситуации может помочь TDD.


          1. mrkaban
            02.11.2022 04:47
            +1

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


      1. KizhiFox
        01.11.2022 10:50
        +1

        Лично я бы сократил до cooking_time_mins (не min, иначе неоднозначно с minimal) и flight_time_sec. Всё ещё прекрасно понятно, но при этом в два раза короче.


        1. OsnovaDT Автор
          01.11.2022 15:21

          Тоже вариант


    1. gou177
      01.11.2022 15:21
      +2

      from typing import NewType
      
      # более строгий
      Minutes = NewType('T', int)
      # менее строгий
      Minutes = int
      
      cooking_time: Minutes = 60

      Есть вариант использования type hints с типом или алиасом вместо суффикса переменной


      1. OsnovaDT Автор
        01.11.2022 15:25
        -1

        Вариант интересный, но тогда при чтении кода не будет видно что cooking_time измеряется в минутах. Придется наводиться на эту переменную, и только тогда мы увидим тип Minutes. Т.е. не получится нормального беглого чтения


  1. saurterrs
    31.10.2022 13:59
    +6

    Так я и не могу принять в своё сердце type hint в питоне. Всё прекрасно работало в докстрингах, с описанием типов аргументов, мета информации и возвращаемого значения. Оно выглядело эстетически лучше, парсилось любым IDE и могло быть автоматически свёрнуто, чтобы не отъедать место.

    Видеть современный питонячий код с type hint, с раздутыми скобками в аргументах функций, с импортом всего и вся чтобы код не падал из-за опять таки тайп хинтинга - сердце кровью обливается.


    1. OsnovaDT Автор
      31.10.2022 14:04

      А можете привести пример с описанием в докстрингах? Просто не уверен что правильно вас понял


      1. saurterrs
        31.10.2022 14:37
        +6

        def some_function_with_lots_of_args(
            name,
            position,
            some_list = None,
            bad_desision = {}
        ):
            """
            This function used for testing purposes
        
            Args:
                name (str): the name of some poor soul
                position (common.common_enums.PositionEnum): the target position of the 
                    person
                some_list ([common.departments] | None): assosiated departments
                bad_desision (dict): some additional meta, use with cautious
        
            Returns:
                string: Identificator for the person
        
            Raises:
                Attribute error
                common.errors.SomeCustomError: i got tired of making uo descriptions
            """
            

        Например, пример на гуглостайловых докстрингов (подобного вида использовали в работе). Мог где то ошибиться, потому что давно не писал на питоне.

        Не скажу за все IDE, но тот же pycharm спокойно умел парсить эти докстринги и выполнять статический анализ на их основе. При этом можно было обойтись без импортов всего из common в файле, если оно явно не используется.


        1. OsnovaDT Автор
          31.10.2022 15:00
          +3

          Понял, спасибо. Да, выглядит интересно и понятно. Наверно, писать докстрингами или хинтами - это дело вкуса. Я вот такие докстринги никогда не писал и как-то привык к хинтам. Имхо с ними код выглядит короче, а вместо описания аргумента, можно сделать ему понятное название.


        1. yurass13
          31.10.2022 16:03
          +2

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


          1. OsnovaDT Автор
            31.10.2022 16:08

            Да, нужно находить золотую середину. Например тот же type hint нет смысла указывать для __init__, ибо все и так знают для чего этот метод и что он возвращает


          1. saurterrs
            31.10.2022 16:43

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


  1. SergeiMinaev
    31.10.2022 15:21
    +2

    Идеально:

    # Код файла constants.py
    MIN_IN_SECONDS = 60
    HOUR_IN_SECONDS = MIN_IN_SECONDS * 60
    # Код файла script.py
    from constants import HOUR_IN_SECONDS
    flight_time_in_seconds = HOUR_IN_SECONDS * 3

    В питоне нехватает стандартизации таких вещей. Нравится, как сделано в расте:

    use chrono::Duration;
    
    let flight_time: Duration = chrono::hours(3);

    Обратите внимание, что из названия переменной пропала часть "_in_seconds", потому что это не int. То есть имеется универсальная Duration, которую можно создавать из секунд, часов и чего угодно в обе стороны, и которую поддерживают все.


    1. OsnovaDT Автор
      31.10.2022 15:28
      +1

      Да, выглядит удобно. В Python, насколько я знаю, такого нет. Можно конечно создавать свой такой класс, но каждый раз это делать - не особо хочется


      1. SuperFly
        31.10.2022 19:06
        +7

        Ну в это конкретном случае, я б порекомендовал datetime.timedelta(hours=3). А вот к MIN_IN_SECONDS & HOUR_IN_SECONDS у меня были б большие вопросы на ревью


        1. OsnovaDT Автор
          31.10.2022 19:07

          А что не так с этими константами?


          1. SuperFly
            31.10.2022 19:33
            +7

            Если предположить, что по каким-то причинам нельзя использовать timedelta? Ну это скорей на уровне ощущения.

            Одно из главных назначений констант - придать смысла бессмысленным числам (мы же тут про числовые константы). Т.е. такой код я поддерживаю

            # Developer's performance is measured in lines of code
            LOC_PER_HOUR = 100
            WORKING_HOURS_PER_DAY = 8
            LOC_PER_DAY = LOC_PER_HOUR * WORKING_HOURS_PER_DAY
            WORKING_DAYS_PER_WEEK = 5
            LOC_PER_WEEK = LOC_PER_DAY * WORKING_DAYS_PER_WEEK
            

            Но в случае если переменная называется flight_time_in_seconds, то 60 там не бессмысленно. Можно сказать, что это уже мета-константа в мозгу, и на ревью я б предложил остановиться на 60 * 60 * 3


            1. OsnovaDT Автор
              31.10.2022 20:58

              Понял о чем вы, спасибо за хороший пример. И соглашусь с вами, но все же если брать пример из статьи, то лично я быстрее пойму такую запись: HOUR_IN_SECONDS * 3, чем: 60 * 60 * 3

              И быстрее пойму куда идти чтобы поменять это число. Но это имхо


              1. funca
                01.11.2022 00:01
                +1

                Представьте, что мы не пишем код, а удаляем flight_time_in_seconds. Где гарантии, что HOUR_IN_SECONDS не останется висеть мертвым, уже никому не нужным кодом? Как понять, что на HOUR_IN_SECONDS ни кто больше не завязан и его удаление будет безопасным? Значит нужно заблаговременно позаботиться и убрать лишнее из all (а ещё лучше в приватный модуль). Вау, архитектура.

                С другой стороны, всех этих проблем можно легко избежать, если не плодить сущности сверх меры. Если не подходит timedelta (допустим, нам эту константу нужно сериализовывать), и нужно лишний раз напомнить читателям кода про нюансы арифметики, я бы рекомендовал ограничиться комментарием как в "Лучше, но всё ещё плохо". К тому же, IDE потом будет выводить этот коммент в подсказке.


                1. OsnovaDT Автор
                  01.11.2022 01:07
                  +1

                  В целом согласен. В данном примере еще и KISS нарушается.

                  К тому же, IDE потом будет выводить этот коммент в подсказке.

                  Какая именно IDE? VS Code например не выводит комменты как подсказку


                  1. funca
                    01.11.2022 19:29

                    Я напутал. Нужен докстринг, и они в питоне пишутся снизу:

                    x = 42
                    """42 is the answer"""
                    
                    x  # докстринг будет в подсказке

                    но смысл тот же :)


                    1. OsnovaDT Автор
                      01.11.2022 21:16

                      Ого, впервые такую запись вижу. Спасибо


  1. whoisking
    31.10.2022 17:20

    1. __new__ (если такой метод используется в классе);

    2. __init__;

    3. Остальные магические методы;

    4. Public-методы;

    5. Protected-методы;

    6. Private-методы.

    Protected в Python? Первый раз услышал, пошёл в гугл, оказывается методы с одним нижним подчёркиванием считаются protected, но по факту они ни разу не protected, в чём смысл тогда? Обычно сколько встречаю, считается нормой как раз приватные объявлять с одним нижним подчёркиванием, что является просто согласием в python сообществае, т.к. два нижних всё равно по факту приватности не дают, а тут вдруг protected...


    1. OsnovaDT Автор
      31.10.2022 17:55
      +1

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

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

      Да, как таковой приватности нет, но так работает Python, ему она и не нужна. Кстати есть одна библиотека с декораторами private и public, которые являются подобием private и public в других языках, например C++. Но, к сожалению, не помню ее названия


    1. stepalxser
      31.10.2022 18:34

      Protected на уровне соглашения - в любой произвольной версии интерфейс может поменяться и ты можешь использовать только на свой страх и риск.


      1. OsnovaDT Автор
        31.10.2022 18:40

        Если такое произойдет, то скорее всего в мажорной версии, что не так страшно.


    1. Andrey_Solomatin
      31.10.2022 18:53
      +3

      В документации эти типы называются `non-public part of the API` (одиночное подчёркивания, применяется для функций, классов, аттрибутов классов, переменных) и `class-private members` (двойное подчёркивание, только аттрибуты класса).

      https://docs.python.org/3/tutorial/classes.html#private-variables

      Оба случая поддерживаются на уровне языка.

      "non-public part of the API" не импортируются при импортах звёздочкой.
      А приватные методы класса не оверрайдятся при наследовании.


      1. OsnovaDT Автор
        31.10.2022 19:04

         (двойное подчёркивание, только аттрибуты класса).

        А как же методы?



    1. sepulkary
      01.11.2022 08:53

      Двойное подчеркивание не помешает вам использовать метод, просто усложнит доступ, заставляя использовать _<ClassName>__<fieldName> (это называется name mangling), намекая, что что-то пошло не так.


  1. code_panik
    01.11.2022 02:04
    +4

    MIN_IN_SECONDS - неудачное, по-моему, название для переменной. Транслит с русского на английский, как тут "минута в секунд(ах/ы?)", в целом кажется неудачным подходом к именованию. Напоминает первые лабораторные студентов по программированию. Лучше SECONDS_PER_MINUTE или MINUTE_TO_SECONDS.


    1. OsnovaDT Автор
      01.11.2022 02:17

      В первых лаборатнорных переменные обычно именуются как-то так: a, b, c, var, list, value.

      MIN_IN_SECONDS - минута в секундах. Также как вес в килограммах WEIGHT_IN_KILOGRAMS


      1. TiesP
        01.11.2022 05:01
        +4

        MIN_IN_SECONDS - минута в секундах. Также как вес в килограммах WEIGHT_IN_KILOGRAMS

        Нет, это не то же самое) "Минута в секундах" это как "Тонна в килограммах". А если вы хотите назвать по аналогии с WEIGHT_IN_KILOGRAMS, то было бы TIME_IN_SECONDS


        1. OsnovaDT Автор
          01.11.2022 15:40

          Согласен. Но как и "Тонна в килограммах", так и "Минута в секундах" звучат на мой взгляд понятно. Т.е. "сколько будет одна тонна в килограммах" и "сколько будет одна минута в секундах"


  1. sepulkary
    01.11.2022 08:43
    +2

    Плохо:

    cat_name: str = "Tom"

    Не согласен с предложением избегать type hint, «если тип переменной и так понятен».

    Прямо здесь, прямо сейчас type hint выглядит, действительно, несколько наивно, но когда сотней строк ниже появится желание засунуть в cat_name что-то другое (bytes, например), у IDE будет возможность побурчать.


    1. OsnovaDT Автор
      01.11.2022 15:38

      Как-то до этого не додумался. Спасибо.

      у IDE будет возможность побурчать.

      И сам программист, пожалуй, поймет что делает что-то не то)


  1. Helltraitor
    01.11.2022 12:00
    +2

    Не используйте это правило если пишите на Django, и в вашем коде есть функция gettext. Её принято заменять на нижнее подчёркивание.

    Не используйте нижнее подчеркивание как функцию, поскольку ее принято использовать для неиспользуемых элементов (практически во всех языках).

    Для функции перевода используйте сокращение t


    1. OsnovaDT Автор
      01.11.2022 15:36

      Тогда уж лучше оставить имя функции как есть, чтобы при её поиске не приходилось бегать по всем t в коде.