Pull to refresh

Comments 29

Ваш код плохо читается не из-за отсутствия enum, а из-за игнорирования pep8 и ужасного нейминга

Можно примеры, пожалуйста? PyCharm не ловит ни одного нарушения пепа, и как можно оценивать нейминг не имея представления о предметной области проекта?

  1. Compound statements (multiple statements on the same line) are generally discouraged. В комплекте с код-блоками хабра еще и приходится мотать ваш код влево-вправо, чтобы прочитать.

  2. Don’t compare boolean values to True or False using ==

  3. Не нужно знать предметную область, чтобы штуки типа self.d или self.project.p были чем-то кроме как примерами плохого нейминга.

второй пункт не работает, если переменная помимо False еще может принимать значение None

второй пункт не работает, если переменная помимо False еще может принимать значение None


== как-то по другому работает с None чем is?

pip8 не предполагает использования is тоже:

# Correct:
if greeting:
# Wrong:
if greeting == True:
# Wrong:
if greeting is True:

Но для того, чтобы различить False и None все равно придется писать if greeting == False или if greeting is False, просто if not greeting не сработает.

  1. Generally discouraged. Если это return и он помещается в 120 символов, то это дело личного предпочтения.

  2. Функция буквально также возвращает None

  3. Это является плохим неймингом в отрыве от проекта; в рамках проекта есть ощутимое количество математики с векторами, из-за чего были заимствованы сокращения в математическом стиле, и d и p являются специфическими для проекта терминами. В документации есть табличка со списком всех терминов специфичных для проекта. Сокращения имён переменных специфичные для предметной области это распространённая практика в питоне. Например, в пандас это df.

Например, в пандас это df.


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

В Kotlin существует неявная переменная it, используемая в сокращённых лямбдах. В JQuery есть $. В циклах рутинно используются однобуквенные переменные, несмотря на то что зачастую эти циклы бывают довольно большими и это даже в какой-то степени вредит читаемости. В принципе использование сокращений переменных в современном питоне является минимальным нарушением стиля кода, вот например двухбуквенная переменная в кодовой базе джанго, которую я нашёл за две минуты. Правилом "нельзя использовать однобуквенные переменные" можно легко пренебречь, особенно если это сокращение распространённое, задокументированное и с ним знакомы все разработчики. Программирование это не религия, в нём нет догм, и в некоторых ситуациях слепое следование правилам приводит к ухудшению качества кода.

Только вот it подсвечивается ide (а Котлин в 99% случаев используется с одной единственной ide) и при появлении вложенных конструкций настоятельно рекомендуется указывать иное имя.

PyCharm не ловит ни одного нарушения пепа

Может быть у вас линтер не включен?

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

Я использую black и ruff. Ну и чтобы не париться с настройкой сделать шаблон для этого. https://github.com/Cjkjvfnby/project_template

Это называется алгебраические типы данных (algebraic data types) и есть несколько библиотек которые их реализуют

Это альтернативное решение, но в данном случае оно кажется мне менее удобным. Например, через стандартные аннотации питона, поддерживающие алгебраические типы данных, мне приходит в голову следующее решение:

class TargetChange:
    Nothing = object()
    To = NewType("To", Optional[int2])

TargetChangeType = TargetChange.Nothing | TargetChange.To

Субъективно это менее компактно и менее читаемо, надо прописывать все члены дважды: в группе TargetChange и в объявлении типа. Вдобавок если потом делать match, то нельзя писать `case TargetChange.To(x)`, можно только `case (x, y)` или `case p`.

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

А чем, собственно, не устроили обычные Enum?

Обычные Enum по умолчанию не поддерживают вложенные типы. Enum раста по сути является объединением enum-а и union-а, что на практике показало себя как очень удобное решение.

У автора не совсем enum. Изначально энум это перечисление. Как уже раньше сказали это алгебраические типы. Есть перечесления по типу объекта, но работаете вы с экземплярами.

if self.subject is None: return False

за подобные однострочники такое бьют ногами, сильно
делайте нормально в пару строк

вы же потом смогли нормально написать

if self.period.step():
    return self.subject.p

Я закинул библиотеку в PyPI и GitHub


С PyPi поторопились. Pip умеет устанавливать прямо с GitHub

В тестах нет ни единого ассерта. Они точно что-то тестируют?

python_requires=">=3.6",

Сдалайте GitHub actions с матрицей питонов погонять тесты. Заодно примеры обновите для 3.6.

В тестах нет ни единого ассерта. Они точно что-то тестируют?

https://github.com/girvel/rust_enum/blob/master/tests/test_enums.py#L15

https://github.com/girvel/rust_enum/blob/master/tests/test_enums.py#L16

Сдалайте GitHub actions с матрицей питонов погонять тесты. Заодно примеры обновите для 3.6.

Не думаю что это эффективное вложение времени, учитывая что это библиотека из 17 строк и она теряет половину полезности без pattern matching из 3.10. Но вообще на 3.6 это действительно не будет работать без датаклассов, которые появились в 3.7, я записал себе issue.

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

Не думаю что это эффективное вложение времени, учитывая что это библиотека из 17 строк и она теряет половину полезности без pattern matching из 3.10

Это в первый раз долго, а потом просто скопировать воркфлоу и поправить пару значений.

Но вообще на 3.6 это действительно не будет работать без датаклассов, которые появились в 3.7, я записал себе issue.

Я бы просто поднял минимальную версию до 3.10 и не парился с поддержкой старых версий.

Также возможное решение, но оно требует ощутимо больше шаблонного кода.

Я бы сказал, что как раз меньше шаблонного кода. И минус одна зависимость.

Выше я приводил пример работы с enum через typing и подробно расписал почему это худшее решение.

Нужно будет поиграться с этим матчингом, а то в основных проектах еще 3.9.

Хотя когда смотрел это видео, мне показалось, что этот синтаксический сахар не такой уж и сладкий. https://www.youtube.com/watch?v=ZTvwxXL37XI

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

Поддержу комментаторов выше. Хоть тема поста и интересна, но читать ваш код весьма сложно.

Поправил чтобы было проще читать на хабре.

Sign up to leave a comment.

Articles