Подтвердить что ты не робот

Почему в Python отсутствует явная проверка пустоты (например, `is Empty`)

Zen of Python говорит: "Явный лучше, чем неявный". Тем не менее "питонический" способ проверки пустоты заключается в использовании неявной логичности:

if not some_sequence:
    some_sequence.fill_sequence()

Это будет верно, если some_sequence является пустой последовательностью, но также и если она None или 0.

Сравните с теоретической явной проверкой пустоты:

if some_sequence is Empty:
    some_sequence.fill_sequence()

При некотором неприемлемо выбранном имени переменной неявное booleaness для проверки пустоты становится еще более запутанным:

if saved:
    mess_up()

Сравните с:

if saved is not Empty:
    mess_up()

Смотрите также: "Python: как лучше всего проверить, пуст ли пул?". Мне показалось, что самый проголосовавший ответ утверждает, что неявный питонический.

Так есть ли более высокая причина, по которой не существует явной проверки пустоты, например, например is Empty в Python?

4b9b3361

Ответ 1

Причина, по которой нет is Empty, поразительно проста, как только вы понимаете, что делает оператор is.

Из руководства python:

Операторы is и is not проверяют идентичность объекта: x is y истинно тогда и только тогда, когда x и y являются одним и тем же объектом. x is not y дает обратное значение истинности.

Это означает, что some_sequence is Empty проверяет, является ли some_sequence тем же объектом, что и Empty. Это не может работать так, как вы предполагали.

Рассмотрим следующий пример:

>>> a = []
>>> b = {}

Теперь предположим, что в python есть эта конструкция is Empty:

>>> a is Empty
True
>>> b is Empty
True

Но так как оператор is проверяет личность, это означает, что a и b идентичны Empty. Это, в свою очередь, должно означать, что a и b идентичны, но они не являются:

>>> a is b
False

Итак, чтобы ответить на ваш вопрос "почему в python нет is Empty?": потому что is проверяет личность.

Чтобы иметь конструкцию is Empty, вы должны либо взломать оператор is, чтобы означать что-то другое, либо создать какой-то магический объект Empty, который каким-то образом обнаруживает пустые коллекции, а затем будет идентичен им.

Вместо того, чтобы спрашивать, почему нет is Empty, вы должны спросить, почему нет встроенной функции isempty(), которая вызывает специальный метод __isempty__().

Итак, вместо использования неявной логичности:

if saved:
  mess_up()

у нас есть явная пустая проверка:

if not isempty(saved):
  mess_up()

где класс saved имеет метод __isempty__(), реализованный для некоторой разумной логики.

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

Конечно, вы можете легко определить свою собственную функцию isempty():

def isempty(collection):
  try:
    return collection.__isempty__()
  except AttributeError:
    # fall back to implicit booleaness but check for common pitfalls
    if collection is None:
      raise TypeError('None cannot be empty')
    if collection is False:
      raise TypeError('False cannot be empty')
    if collection == 0:
      raise TypeError('0 cannot be empty')
    return bool(collection)

а затем определите метод __isempty__(), который возвращает логическое значение для всех ваших классов коллекции.

Ответ 2

Полиморфизм в if foo: и if not foo: не является нарушением "неявного vs явного": он явно делегирует проверяемому объекту задачу узнать, истинно это или ложно. То, что это означает (и как лучше всего это проверять), очевидно, должно и должно зависеть от типа объекта, поэтому руководство по стилю задает делегацию. На самом деле код приложения на самом деле утверждает, что он лучше знает, чем объект будет высотой безумия.

Кроме того, X is Whatever всегда, неизменно означает, что X точно тот же объект, что и любой. Сделать совершенно уникальное исключение для Empty или любое другое значение Whatever было бы абсурдным - трудно представить себе более непифонический подход. И "быть точно таким же объектом", очевидно, является транзитивным, поэтому вы больше никогда не можете иметь разные пустые списки, пустые наборы, пустые дикты... поздравления, вы только что разработали совершенно непригодный и бесполезный язык, где каждый пустой контейнер безумно "рушится" до единственного пустого объекта-контейнера (просто представьте себе удовольствие, когда кто-то пытается мутировать пустой контейнер...?!).

Ответ 3

Я согласен, что иногда if foo: не явствует для меня, когда я действительно хочу сказать читателю код, что это пустота, которую я тестирую. В таких случаях я использую if len(foo):. Явно достаточно.

Я на 100% согласен с тем, что Alex w.r.t is Empty является непитоническим.

Ответ 4

Считайте, что Lisp использует() пустой список или его символ NIL уже несколько лет как False и T или что-то не NIL как True, но в целом вычисление Истины уже произвело некоторый полезный результат, который не нужно воспроизводить, если необходимо, Посмотрите также метод разделения строк, где средний результат работает очень хорошо, так как управление с непустым - это соглашение True.

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

Для меня я предпочел бы, чтобы Python имел False as() или [] вместо 0, но так оно и есть. Тогда было бы естественнее использовать не [] как непустую. Но теперь() не [] имеет значение True, поэтому вы можете использовать:

emptyset = set([])    
if myset == emptyset:

Если вы хотите быть явным из пустого случая набора (не устанавливается myset ([]))

Мне самому нравится if not myset как мой комментатор.

Теперь мне пришло в голову, что, возможно, это ближе всего к явным not_empty:

if any(x in myset for x in myset): print "set is not empty"

и поэтому пустое будет:

if not any(x in myset for x in myset): print "set is empty"

Ответ 5

Существует явная проверка пустоты для iterables в Python. Он пишется not. Что там скрыто? not дает True, когда iterable пуст, и дает False, когда он не пуст.

В чем именно вы возражаете? Имя? Как вам сказали другие, это, конечно, лучше, чем is Empty. И это не так неграмматично: учитывая, как вещи обычно называются в Python, мы можем представить последовательность с названием widgets, содержащую, что удивительно, некоторые виджеты. Тогда,

if not widgets:

можно прочитать как "если нет виджетов...".

Или вы возражаете против длины? Явное не означает подробный, это два разных понятия. У Python нет метода addition, он имеет оператор +, который полностью явственен, если вы знаете тип, к которому вы его применяете. То же самое с not.