Причина "всего" и "любого" результата в пустых списках
В Python встроенные функции all
и any
возвращает True
и False
соответственно для пустых итераций. Я понимаю, что если бы все было наоборот, этот вопрос все равно можно было бы спросить. Но я хотел бы знать, почему это конкретное поведение было выбрано. Было ли это произвольным, т.е. может ли это так же легко было иначе, или есть основная причина?
(Причина, о которой я прошу, - это просто потому, что я никогда не помню, что это такое, и если бы я знал обоснование, то я мог бы. Кроме того, любопытство.)
Ответы
Ответ 1
Как насчет некоторых аналогов...
У вас есть ящик для носка, но он пуст. Он содержит черный носок? Нет - у вас совсем нет носков, поэтому у вас, конечно же, нет черного. Очевидно, что any([])
должен возвращать false - если он вернёт true, это будет контринтуитивно понятным.
Случай для all([])
немного сложнее. См. Статью Википедии о пустое правду. Другая аналогия: если в комнате нет людей, то все в этой комнате могут говорить по-французски.
Математически all([])
можно написать:
, где множество A пусто.
Существует значительная дискуссия о том, следует ли считать пустое высказывание истинным или нет, но с логической точки зрения он имеет наибольший смысл:
Основной аргумент в пользу того, что все пустое истинное утверждение истинно, таков: Как объясняется в статье о логических условностях, аксиомы пропозициональных логика подразумевает, что если P ложно, то P = > Q истинно. То есть, если мы принимаем эти аксиомы, мы должны признать, что пустое истинное утверждение действительно истинно.
Также из статьи:
Кажется, нет прямой причины выбирать истину; это просто то, что на нас взорвутся, если мы этого не сделаем.
Определение оператора "vacuously true" для возврата false в Python нарушит принцип наименьшего удивления.
Ответ 2
Одним из свойств any
является его рекурсивное определение
any([x,y,z,...]) == (x or any([y,z,...]))
Это означает
x == any([x]) == (x or any([]))
Равенство верно для любого x
тогда и только тогда, когда any([])
определено как False. Аналогично для all
.
Ответ 3
Я считаю, что all([])==True
, как правило, сложнее понять, поэтому вот коллекция примеров, где я считаю, что поведение, очевидно, верно:
- Фильм подходит для слушания, если все диалоги в фильме озаглавлены. Фильм без диалога по-прежнему подходит для слабослышащих.
- Комната без окон темная, когда все огни внутри выключены. Когда внутри нет света, темно.
- Вы можете пройти через безопасность в аэропорту, когда все ваши жидкости содержатся в бутылках по 100 мл. Если у вас нет жидкостей, вы все равно можете пройти через безопасность.
- Вы можете поместить мягкий пакет через узкий слот, если все предметы в сумке уже, чем слот. Если сумка пуста, она все еще помещается в слот.
- Задача готова к запуску, когда все ее предпосылки выполнены. Если задача не имеет предварительных условий, она готова к запуску.
Ответ 4
Я думаю, что они реализованы таким образом
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
не уверены, что они реализованы таким образом, хотя
Ответ 5
Perl 6 также принимает позицию, что all()
и any()
в пустых списках должны служить нормальными базовыми блоками для их соответствующих операторов сокращения, и поэтому all()
истинно, а any()
- false.
То есть, all(a, b, c)
эквивалентно [&] a, b, c
, что эквивалентно a & b & c
(сокращение на "junctive and", но вы можете игнорировать переходы и считать его логичным и для этого сообщения), а any(a, b, c)
эквивалентно [|] a, b, c
, что эквивалентно a | b | c
(сокращение от "junctive or" operator - снова, вы можете притворяться, что это то же, что логично или ничего не пропало).
Любой оператор, который может иметь приложенное к нему сокращение, должен иметь определенное поведение при уменьшении 0 членов, и обычно это делается с помощью естественного элемента идентификации - например, [+]()
(уменьшение сложения по нулевым членам) 0, поскольку 0 - аддитивное тождество; добавление нуля к любому выражению оставляет его неизменным. [*]()
также равно 1, потому что 1 является мультипликативным тождеством. Мы уже говорили, что all
эквивалентно [&]
, а any
эквивалентно [|]
- ну, истина есть и-тождество, а ложность - или-тождество - x, а True - x, а x или False - x. Это делает неизбежным, что all()
должен быть истинным, а any()
должен быть ложным.
Чтобы поместить его в совершенно другую (но практическую) перспективу, any
является защелкой, которая начинается с false и становится истиной всякий раз, когда видит что-то истинное; all
- это защелка, которая начинается с истины и становится ложной всякий раз, когда видит что-то ложное. Предоставление им аргументов не означает, что у них нет шансов изменить состояние, поэтому вы просто спрашиваете их, каково их состояние "по умолчанию".:)
Ответ 6
Для общего интереса здесь сообщение в блоге, в котором GvR предлагает любые/все с примерной реализацией, такой как gnibbler и quanifiers в ABC.
Ответ 7
any
и all
имеют такой же смысл в python, как и везде:
-
any
истинно, если хотя бы одно верно.
-
all
неверно, если хотя бы один не является истинным
Ответ 8
Это скорее комментарий, но код в комментариях работает не очень хорошо.
В дополнение к другим логическим основам для того, почему 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([])
было истинным.