Причина «все» и «любой» результат в пустых списках - PullRequest
24 голосов
/ 18 июля 2010

В Python встроенные функции all и any возвращают True и False соответственно для пустых итераций. Я понимаю, что если бы все было наоборот, этот вопрос все равно можно было бы задать. Но я хотел бы знать, почему было выбрано именно это поведение. Было ли это произвольно, т.е. могло ли это быть так же легко и наоборот, или есть причина?

(Причина, по которой я спрашиваю, состоит в том, что я просто не помню, что есть что, и если бы я знал причину, стоящую за этим, я мог бы. Также, любопытство.)

Ответы [ 10 ]

36 голосов
/ 18 июля 2010

Как насчет некоторых аналогий ...

У вас есть ящик для носка, но в настоящее время он пуст. Содержит ли он черный носок? Нет - у вас вообще нет носков, поэтому у вас наверняка нет черного. Ясно, что any([]) должен возвращать false - если он вернул true, это было бы нелогично.

Случай для all([]) немного сложнее. См. Статью в Википедии о бессмысленной правде . Еще одна аналогия: если в комнате нет людей, то все в этой комнате могут говорить по-французски.

Математически all([]) можно записать:

image, где множество A пусто.

В настоящее время ведутся серьезные споры о том, следует ли считать пустые утверждения правдивыми или нет, но с логической точки зрения это имеет смысл:

Основной аргумент, что все пусто истинные утверждения являются истинными, заключается в следующем: Как объясняется в статье о логических условных выражениях , аксиомы логики высказываний влекут за собой то, что если P ложно, то P => Q правда. То есть, если мы примем эти аксиомы, мы должны признать, что пусто истинные утверждения действительно верны.

Также из статьи:

Кажется, нет прямой причины выбирать истину; это просто, что вещи взрываются перед нами, если мы не делаем.

Определение «пусто истинного» оператора для возврата false в Python нарушило бы принцип наименьшего удивления .

20 голосов
/ 18 июля 2010

Одним свойством any является его рекурсивное определение

any([x,y,z,...]) == (x or any([y,z,...]))

Это значит

x == any([x]) == (x or any([]))

Равенство является правильным для любого x тогда и только тогда, когда any([]) определено как False. Аналогично для all.

7 голосов
/ 17 апреля 2012

Я считаю, что all([])==True, как правило, сложнее понять, поэтому вот несколько примеров, в которых я считаю, что поведение очевидно правильное:

  • Фильм подходит для слабослышащих, если1005 * все диалоговое окно в фильме с субтитрами.Фильм без диалога по-прежнему подходит для слабослышащих.
  • В комнате без окон темно, когда все внутреннее освещение выключено.Когда внутри нет света, темно.
  • Вы можете пройти через службу безопасности аэропорта, когда все ваши жидкости содержатся в бутылках по 100 мл.Если у вас нет жидкости, вы все равно можете пройти через охрану.
  • Мягкую сумку можно пропустить через узкое отверстие, если все элементы в пакете уже, чем отверстие.Если сумка пуста, она все равно проходит через слот.
  • Задание готово к запуску, когда все его предпосылки выполнены.Если у задачи нет предварительных условий, она готова к запуску.
4 голосов
/ 18 июля 2010

Perl 6 также занимает позицию, что all() и any() в пустых списках должны служить в качестве нормальных базовых вариантов для их соответствующих операторов сокращения, и поэтому all() - это истина, а any() - это ложь.

То есть, all(a, b, c) эквивалентно [&] a, b, c, что эквивалентно a & b & c (сокращение на оператор "junctive and", но вы можете игнорировать переходы и считать это логичным и для этого поста) и any(a, b, c) эквивалентно [|] a, b, c, что эквивалентно a | b | c (сокращение на оператор "junctive или" - опять же, вы можете притвориться, что оно такое же, как логическое или ничего не пропустить).

Любой оператор, к которому может быть применено сокращение, должен иметь определенное поведение при сокращении 0 терминов, и обычно это делается с помощью элемента естественной идентичности - например, [+]() (сокращение сложения через нулевые термины) 0, потому что 0 аддитивная идентичность; добавление нуля к любому выражению оставляет его неизменным. [*]() аналогично 1, потому что 1 - мультипликативная идентичность. Мы уже говорили, что all эквивалентно [&], а any эквивалентно [|] - хорошо, правда - это и -идентичность, а ложь - или -dentity - x и True - это x, а x или False - это x. Это делает неизбежным, что all() должно быть истинным, а any() должно быть ложным.

Чтобы поместить это в совершенно иную (но практическую) перспективу, any - это защелка, которая начинается с ложного и становится истинной всякий раз, когда она видит что-то истинное; all - это защелка, которая начинается с истины и становится ложной всякий раз, когда она видит что-то ложное. Если у них нет аргументов, это значит, что у них нет шансов изменить состояние, поэтому вы просто спрашиваете их, какое у них состояние «по умолчанию». :)

4 голосов
/ 18 июля 2010

Я думаю, что они реализованы таким образом

def all(seq):
    for item in seq:
        if not item:
            return False
    return True

def any(seq):
    for item in seq:
        if item:
            return True
    return False

не уверен, что они реализованы таким образом, хотя

2 голосов
/ 18 июля 2010

any и all имеют в Python то же значение, что и везде:

  • any истина, если хотя бы одна истина
  • all неверно, если хотя бы одно неверно
2 голосов
/ 18 июля 2010

Для общего интереса, вот сообщение в блоге , в котором GvR предлагает любую / все с примером реализации, таким как gnibbler и квантификаторы ссылок в ABC.

1 голос
/ 26 сентября 2018

Официальная причина неясна, но из документов (подтверждающих пост @John La Rooy):

all(iterable)

Возвращает True, если все элементы итерируемого являются истинными (или если итерируемое пусто). Эквивалентно:

   def all(iterable):
       for element in iterable:
           if not element:
               return False
      return True

any(iterable)

Возвращает True, если какой-либо элемент итерируемого равен true. Если итерация пуста, вернуть False. Эквивалентно:

   def any(iterable):
       for element in iterable:
           if element:
               return True
       return False

См. Также CPython-реализацию и комментарии .

1 голос
/ 12 ноября 2014

Это действительно больше комментарий, но код в комментариях работает не очень хорошо.

В дополнение к другим логическим основам, почему any() и all() работают так, как они, онидолжны иметь противоположные «базовые» случаи, чтобы это соотношение сохранялось:

all(x for x in iterable) == not any(not x for x in iterable)

Если iterable нулевой длины, вышеприведенное все равно должно сохраняться.Следовательно,

all(x for x in []) == not any(not x for x in [])

, что эквивалентно

all([]) == not any([])

И было бы очень удивительно, если бы any([]) было тем, которое истинно.

0 голосов
/ 28 февраля 2019
  • all([]) == True: ноль из нуля - отметьте
  • any([]) == False: кто-нибудь? никто - провал
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...