Конкретные примеры максимы Python «только один способ сделать это» [закрыто]

34

Я изучаю Python и заинтригован следующим пунктом в PEP 20 Zen of Python :

Должен быть один - и желательно только один - очевидный способ сделать это. Хотя этот путь поначалу может быть неочевидным, если вы не голландец.

Может ли кто-нибудь предложить какие-то конкретные примеры этой максимы? Я особенно заинтересован в контрасте с другими языками, такими как Ruby. Частью философии дизайна Ruby (созданной на Perl, я думаю?) Является то, что множество способов сделать это - A Good Thing. Может кто-нибудь предложить несколько примеров, показывающих плюсы и минусы каждого подхода. Обратите внимание, я не после ответа, который лучше (который, вероятно, слишком субъективен, чтобы когда-либо отвечать), а скорее объективного сравнения двух стилей.

Чарльз Ропер
источник

Ответы:

47

По сравнению с такими языками, как Perl, Python имеет ограниченное количество управляющих конструкций:

  • только ifи нет unless,
  • только forто, что перебирает последовательности и нет foreachили C-стиль for,
  • только whileто, что проверяет условие каждый цикл и нет do-while,
  • только if-elifи нет switch,
  • есть только одна конструкция комментария, #и для каждой строки вы можете сказать, закомментирована она или нет, не глядя на предыдущие строки.

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

Это облегчает анализ исходного кода Python для людей.

Есть попытки быть минимальными, но полными во встроенных типах и стандартной библиотеке.

  • для изменяемого списка вы используете только встроенный listтип; это O (1) для большинства операций, и вам никогда не придется выбирать правильную реализацию,
  • для неизменяемых списков, в равной степени, вы просто используете tupleтип,
  • для карт вы используете единственную встроенную систему, dictкоторая в большинстве случаев чертовски эффективна, не нужно задумываться о том, какую реализацию использовать.

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

Python пытается избежать синтаксического сахара. Но иногда это добавляет синтаксический сахар, чтобы сделать очевидный путь очевидным. Вы можете написать if foo is not Noneвместо, if not (foo is None)потому что «не» в специальном случае. Все еще foo is not Noneчитает легко, не может быть неправильно истолковано, и вам не нужно думать, вы просто пишете очевидную вещь.

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

Ключевым моментом является то, что всегда есть один способ, который предназначен для того, чтобы быть лучшим, все дело. Если существуют другие способы, они не были добавлены как равные альтернативы (как ifи unless), а просто раскрывают внутреннюю работу. Медленно, но неуклонно такие альтернативы устаревают (не исключаются!) За счет усиления известного лучшего механизма.

Декораторы переносят вызовы функций АОП. До версии 2.6 вам приходилось использовать __metaclass__магический член для объявления метакласса класса; теперь вы можете использовать тот же синтаксис декоратора для этого тоже. До версии 3.0 у вас было два вида строк: байтово-ориентированные и Unicode, которые вы могли непреднамеренно смешивать. Теперь у вас есть единственный Unicode strи единственный двоично-прозрачный bytes, который вы не можете смешать по ошибке.

9000
источник
3
Так же, как примечание, не забывайте """комментарии (строки документации). Они охватывают несколько строк.
Астхаср
8
Литералы с тройными кавычками являются просто строками, такими же, как и одинарные кавычки, но могут занимать несколько строк без экранирования концов строк. Строковый литерал сразу после объявления считается строкой документа, и это не комментарий, обычно он доступен как __doc__атрибут. Но строки - это область, где Python определенно предоставляет множество «правильных путей»: использовать одинарные, двойные или тройные кавычки, неявно соединять смежные литералы, использовать rдля необработанных литералов и т. Д.
9000
1
Я думаю, что комментарий @ syrion касался «вы всегда можете решить, прокомментирована ли строка или нет, просто взглянув на нее», что неверно из-за «» строк.
blubb
2
«Это облегчает разбор источника Python для людей». <- это субъективно
джигги
Как изменилось объявление метакласса в 2.7? Не удается найти шаблон декоратора в документах 2.7 для метаклассов.
Ник Т
10

Еще пара примеров:
len() это функция вместо метода, присутствующего в каждой последовательности; если сравнивать с Java у вас есть .length, .size(), .getSize()и другие методы , чтобы найти число элементов в последовательности.

Другим примером является тот факт, что .join()этоstring метод, а не метод, присутствующий в каждой последовательности. Вам не нужно знать, является ли параметр соединения списком, набором, пониманием или чем-то еще, он будет работать.

Вито Де Туллио
источник
8

В C есть много возможных способов увеличить значение переменной на единицу:

i++     // Post-increment, returns the number before the increment
++i     // Pre-increment, returns the number after the increment
i += 1 

Каждый в конечном итоге увеличивает ценность i на 1, но каждый немного отличается.

В Python есть только один путь; просто добавьте один.

i += 1

И хотя существует более одного синтаксически правильного способа сделать это (например i = i + 1), вы делаете то же самое с одними и теми же побочными эффектами.


источник
1
Я не эксперт, но этот пример явно нарушает идею "только один способ сделать это". У нас есть два способа сделать это, но какой из них более очевиден? На мой взгляд, первый пример более очевиден, в то время как второй является немного более лаконичным, но не менее читабельным или очевидным для любого программиста, который продвинулся дальше самых основных принципов. Спасибо за ваш ответ - это хорошая пища для размышлений.
Чарльз Ропер
@Peter (и @Charles): На самом деле i = i + 1это присваивание, а не приращение. В питоне приращение есть i += 1. В языках C-стиле , вы можете написать i++, ++iи i += 1.
Джош К
2
Не уверен насчет вашего комментария "много путаницы", все три примера C (вы пропустили i += 1, кстати) дают точно такой же результат. Единственный раз, когда я вижу, что люди запутываются, это когда они предварительно или постинкрементно увеличивают переменную как часть большего выражения, и это обычно быстро исправляется, читая соответствующий раздел справочника по языку. Лично я бы выбрал тот факт, что вы можете ссылаться на пятый символ строки обоими str[4]или *(str+4), но, может быть, это было слишком просто ...
TMN
2
@ TMN: некоторые случаи, как, max(i++, ++i)не могут быть быстро исправлены. C имеет много «неопределенных» и «зависящих от реализации» случаев поведения, все по уважительной причине - но каждый может создать ловушку.
9000
@ TMN: не говоря уже о 4 [str] (допустимо в C, может быть недействительно в C ++).
Ватин
6

Другой возможностью могут быть списки. В Python вы можете сделать это:

new_list = []
    for item in list_of_items:
       if item < 10:
           new_list.append(item)

Но «очевидный» способ (если вы голландец или более хорошо знакомы с Python) заключается в понимании списка:

new_list = [item for item in list_of_items if item < 10]

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

Chelonian
источник
Для отступа и кода: добавьте 4 пробела, тогда он будет соответствовать отступу.
Инка