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

Почему python `any` возвращает значение bool вместо значения?

and и or возвращают последний элемент, который они оценивали, но почему не встроенная функция Python any?

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

def any(l):
    for x in l:
        if x:
            return x
    return x

изменить:

Чтобы добавить к ответам ниже, вот настоящая цитата из того же списка рассылки вашего могущественного императора по этому вопросу:

Всегда ли возвращать True и False или первый faling/pass элемент? Я играл с этим еще до блога и понял, что (если последовательность пуста или все элементы не проходят тест) никогда нельзя заставить работать удовлетворительно: сбор Ничего не странно, если аргумент является итерабельным из bools, и выбор False чувствует себя странно, если аргумент - это итерабельность объектов non-bool.

Гвидо ван Россум (домашняя страница: http://www.python.org/~guido/)

4b9b3361

Ответ 1

Эта проблема возникла в списке рассылки разработчиков Python в 2005 году, когда Guido Van Rossum предложил добавить any и all в Python 2.5.

Bill Janssen запросил, что они будут реализованы как

def any(S):
    for x in S:
        if x:
            return x
    return S[-1]

def all(S):
    for x in S:
        if not x:
            return x
    return S[-1]

Раймонд Хеттингер, который реализовал any и all, ответил, в частности, обращаясь к тому, почему any и all не действуют как and и or:

Со временем я получил обратную связь об этих и других рецептах itertools. Никто не возражал против значений True/False в этих рецептах или в версии Guido.

Версия Guido соответствует нормальному ожиданию того, что все/все будут сказуемое. Кроме того, он избегает ошибок/путаницы, которые люди в настоящее время опыт работы с уникальной реализацией Python "и" и "Или".

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

Список рассылки в значительной степени согласился, оставив реализацию, как вы ее видите сегодня.

Ответ 2

and и or могут быть разумно определены так, чтобы они всегда возвращали один из своих операндов. Однако any и all не могут быть разумно определены всегда, чтобы возвращать значение из их входной последовательности: в частности, они не могут сделать этого, когда список пуст. В этой ситуации оба any и all имеют четко определенный результат: any возвращает False, а all возвращает значение True. Вам придется иногда возвращать логическое значение и иногда возвращать элемент из последовательности, что создает неприятный и удивительный интерфейс. Гораздо лучше быть простым и последовательным.

Ответ 3

Я задал этот же вопрос в python-идеях, и было сказано, что причина заключалась в том, что any() и all() необходимо вернуть значение, когда последовательность пуста, и эти значения должны быть False и True. Это кажется слабым аргументом для меня.

Теперь функции не могут измениться, но я думаю, что они были бы более полезными и лучшими аналогами операторов and и or, которые они обобщают, если они вернули первое значение true-ish или false-ish, они встречаются.

Ответ 4

Поведение and и or существует по историческим причинам.

До того, как Python получил тройную операцию/условное выражение, вы использовали and и or, если хотите использовать значение для условия. Любое такое выражение может быть переписано с помощью синтаксиса условного выражения:

true_val if condition else false_val

По сути, они перегружены двумя функциями, и по соображениям совместимости они не были изменены.

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

Ответ 5

Any возвращает логическое значение, потому что он эффективно обрабатывает свой аргумент как список bools, прежде чем рассматривать, является ли кто-либо из них истинным. Он возвращает элемент, который он оценивает, но это бывает как bool.

Когда вы хотите использовать свою версию Any? Если это в списке bools, то у вас уже есть правильный ответ. В противном случае вы просто защищаете от None и можете быть выражены как:

filter(lambda x: x != None, l)[0]

или

[x for x in l if x != None][0]

Что является более ясным выражением о намерениях.

Ответ 6

Не сразу очевидно, что значение any может быть либо False, либо одним из значений на входе. Кроме того, большинство применений будет выглядеть как

tmp = any(iterable)
if tmp:
   tmp.doSomething()
else:
   raise ValueError('Did not find anything')

Это Взгляд перед прыжком и, следовательно, неспокойный. Сравнить с:

next(i for i in iterable if i).doSomething()
# raises StopIteration if no value is true

Поведение and и or исторически полезно в качестве вставки для условного выражения, недоступного для этого.

Ответ 7

Начиная с Python 3.8 и введением выражений присваивания (PEP 572) (оператор :=), мы можем альтернативно явно захватить свидетельство any выражения или контрпример all выражения all:


Чтобы процитировать пару примеров из описания PEP:

if any(len(long_line := line) >= 100 for line in lines):
  print("Extremely long line:", long_line)
if all((nonblank := line).strip() == '' for line in lines):
  print("All lines are blank")
else:
  print("First non-blank line:", nonblank)