Почему неявно проверять пустоту в Python?
Дзен Python говорит, что явный лучше, чем неявный.
Тем не менее, Pythonic способ проверки коллекции c для пустоты:
if not c:
# ...
и проверка того, что коллекция не пустая, выполняется следующим образом:
if c:
# ...
ditto для всего, что может иметь "нулевую" или "пустоту" (кортежи, целые числа, строки, ни один и т.д.)
Какова цель этого? Будет ли мой код более грубым, если я этого не сделаю? Или это позволяет использовать больше случаев использования (т.е. Какой-то полиморфизм), поскольку люди могут переопределять эти логические принуждения?
Ответы
Ответ 1
Эта лучшая практика не без оснований.
При тестировании if object:
вы в основном вызываете метод __nonzero__
объектов, который может быть переопределен и реализован в соответствии с поведением объекта.
Например, метод __nonzero__
в коллекциях возвращает логическое значение, основанное на том, что коллекция пуста или нет.
(Ссылка: http://docs.python.org/reference/datamodel.html)
Ответ 2
"Простой лучше, чем сложный".
"Чтение рассчитывается".
Возьмем, например, if users
- более читаемо, что if len(users) == 0
Ответ 3
Возможно, сбрасывается первым и третьим элементом:
- Красивая лучше, чем уродливая.
- Простой лучше, чем сложный.
Ответ 4
if c:
# ...
является явным. "If" явно указывает, что следующее выражение будет оцениваться в булевом контексте.
Справедливо утверждать, что
if c == 0:
# ...
понятен, и начинающий программист может согласиться.
Но для опытного программиста (по крайней мере, этого) последнее неяснее, оно избыточно. Я уже знаю, что c будет сравниваться с 0 из-за "if"; Мне не нужно рассказывать дважды.
Ответ 5
Если вы предпочитаете, вы можете ввести if len(lst) > 0
, но какой смысл? Python действительно использует некоторые соглашения, один из них состоит в том, что пустые контейнеры считаются ложными.
Вы можете настроить это с помощью object.__nonzero__(self)
:
Вызывается для реализации значения истины тестирование и встроенная работа BOOL(); должен возвращать False или True, или их целых эквивалентов 0 или 1. Когда этот метод не определен, __len__()
вызывается, если оно определяется, и объект считается true, если его результат отличен от нуля. Если class не определяет ни __len__()
, ни __nonzero__()
, все его экземпляры считается истинным.
Ответ 6
Неявный логический полиморфизм является частью многих языков. Фактически, идиома
if msg:
print str(len(msg)) + ' char message: ' + msg
возможно, происходит из c!
void print_msg(char * msg) {
if (msg) {
printf("%d char message: %s", (int) strlen(msg), msg);
}
}
Нераспределенный указатель должен содержать NULL
, который удобно вычисляет значение false, позволяя избежать ошибки сегментации.
Это такое фундаментальное понятие, что это мешает python отвергнуть его. На самом деле, учитывая довольно неуклюжую версию логического полиморфизма, доступную в c, сразу же (по крайней мере, мне) ясно, что python сделал это поведение более явным, разрешив любому типу иметь настраиваемое, четко определенное логическое преобразование через __nonzero__
.
Ответ 7
Другие уже отметили, что это логическое продолжение традиции (по крайней мере, раньше, C, возможно, раньше), что ноль является ложным в булевом контексте, а ненулевое значение истинно. Другие также уже отметили, что в Python вы можете добиться особых эффектов с помощью специальных магических методов и т.д. (И это прямо ответит на ваш вопрос: "позволяет ли это использовать больше случаев использования?" ) Другие уже отметили, что опытные программисты на Python узнают это соглашение и будут использоваться в соглашении, поэтому он совершенно ясен и ясен для них.
Но, честно говоря, если вам не нравится это соглашение, и вы просто программируете для своего собственного удовольствия и пользы, просто не следуйте ему. Гораздо лучше быть явным, ясным и избыточным, чем быть запутанным, и почти всегда лучше ошибаться на стороне избыточности, чем обфускация.
Тем не менее, когда дело доходит до этого, это не сложное соглашение, чтобы учиться, и если вы кодируете как часть группового проекта, лучше придерживаться конвенций проекта, даже если вы не согласны с ними.
Ответ 8
Пустые списки, оценивающие False и непустые списки, оценивающие True, являются таким центральным соглашением на Python, что оно достаточно явное. Если контекст if-оператора даже сообщает тот факт, что c
является списком, len(c) == 0
не будет более явным.
Я думаю, что len(c) == 0
более явственно, если вы действительно хотите проверить длину, а не магическую нулевую или пустоту, потому что их оценка может отличаться от проверки длины.