Вопрос-Ответ

How do Python's any and all functions work?

Как работают все без исключения функции Python?

Я пытаюсь понять, как работают any() и all() встроенные функции Python.

Я пытаюсь сравнить кортежи так, чтобы, если какое-либо значение отличается, оно возвращалось True и если они все одинаковые, оно возвращалось False. Как они работают в этом случае, чтобы возвращать [False, False, False]?

d является defaultdict(list).

print d['Drd2']
# [[1, 5, 0], [1, 6, 0]]
print list(zip(*d['Drd2']))
# [(1, 1), (5, 6), (0, 0)]
print [any(x) and not all(x) for x in zip(*d['Drd2'])]
# [False, False, False]

Насколько мне известно, это должно выводить

# [False, True, False]

поскольку (1,1) одинаковы, (5,6) различны и (0,0) одинаковы.

Почему он принимает значение False для всех кортежей?


Смотрите Pythonic способ проверки выполнения условия для любого элемента списка для практического использования any.

Переведено автоматически
Ответ 1

Вы можете грубо представить себе any и all как последовательность логических or и and операторов, соответственно.

Любой

any вернется, True когда хотя бы один из элементов соответствует действительности. Прочитайте о тестировании значений на истинность.

ВСЕ

all вернет True только тогда, когда все элементы соответствуют действительности.

Таблица истинности

+-----------------------------------------+---------+---------+
| | any | all |
+-----------------------------------------+---------+---------+
| All Truthy values | True | True |
+-----------------------------------------+---------+---------+
| All Falsy values | False | False |
+-----------------------------------------+---------+---------+
| One Truthy value (all others are Falsy) | True | False |
+-----------------------------------------+---------+---------+
| One Falsy value (all others are Truthy) | True | False |
+-----------------------------------------+---------+---------+
| Empty Iterable | False | True |
+-----------------------------------------+---------+---------+

Примечание 1: Пустой итерируемый регистр объясняется в официальной документации следующим образом

any


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


Поскольку ни один из элементов не является true, он возвращает False в этом случае.

all


Возвращает, True если все элементы iterable имеют значение true (или если iterable пуста).


Поскольку ни один из элементов не является false , он возвращает True в этом случае.


Примечание 2:

Еще одна важная вещь, о которой нужно знать any и all, заключается в том, что выполнение будет прервано в тот момент, когда они узнают результат. Преимущество в том, что не нужно использовать всю итерацию целиком. Например,

>>> multiples_of_6 = (not (i % 6) for i in range(1, 10))
>>> any(multiples_of_6)
True
>>> list(multiples_of_6)
[False, False, False]

Здесь, (not (i % 6) for i in range(1, 10)) это выражение генератора, которое возвращает, True если текущее число в пределах 1 и 9 кратно 6. any выполняет итерацию multiples_of_6 и когда оно встречается 6, оно находит истинное значение, поэтому оно немедленно возвращается True, а остальная часть multiples_of_6 не повторяется. Это то, что мы видим, когда печатаем list(multiples_of_6) результат 7, 8 и 9.

Эта превосходная вещь очень умно использована в этом ответе.


С этим базовым пониманием, если мы посмотрим на ваш код, вы сделаете

any(x) and not all(x)

который гарантирует, что по крайней мере одно из значений соответствует действительности, но не все из них. Вот почему он возвращается [False, False, False]. Если вы действительно хотели проверить, не совпадают ли оба числа.,

print [x[0] != x[1] for x in zip(*d['Drd2'])]
Ответ 2

Как работают функции Python any и all?


any и all принимают итерируемые значения и возвращают True, если какие- либо и все (соответственно) элементы являются True.

>>> any([0, 0.0, False, (), '0']), all([1, 0.0001, True, (False,)])
(True, True) # ^^^-- truthy non-empty string
>>> any([0, 0.0, False, (), '']), all([1, 0.0001, True, (False,), {}])
(False, False) # ^^-- falsey

Если итерируемые значения пусты, any возвращает False и all возвращает True.

>>> any([]), all([])
(False, True)

Сегодня на занятии я демонстрировал all и any студентам. В основном их смущали возвращаемые значения для пустых итерируемых объектов. Объяснение этого таким образом вызвало включение множества лампочек.

Поведение при сокращении

Они, any и all, оба ищут условие, которое позволяет им прекратить вычисление. Первые примеры, которые я привел, требовали, чтобы они вычисляли логическое значение для каждого элемента во всем списке.

(Обратите внимание, что list literal сам по себе не вычисляется лениво - вы могли бы получить это с помощью итератора, но это только для иллюстрации.)

Вот реализация Any and all на Python:

def any(iterable):
for i in iterable:
if i:
return True
return False # for an empty iterable, any returns False!

def all(iterable):
for i in iterable:
if not i:
return False
return True # for an empty iterable, all returns True!

Конечно, реальные реализации написаны на C и гораздо более производительны, но вы могли бы заменить приведенное выше и получить те же результаты для кода в этом (или любом другом) ответе.

all

all проверяет наличие элементов False (чтобы он мог возвращать False), затем возвращает, True если ни один из них не был False.

>>> all([1, 2, 3, 4])                 # has to test to the end!
True
>>> all([0, 1, 2, 3, 4]) # 0 is False in a boolean context!
False # ^--stops here!
>>> all([])
True # gets to end, so True!

any

Способ any работы заключается в том, что он проверяет, чтобы элементы были True (поэтому он может возвращать True), then it returnsFalseif none of them wereTrue`.

>>> any([0, 0.0, '', (), [], {}])     # has to test to the end!
False
>>> any([1, 0, 0.0, '', (), [], {}]) # 1 is True in a boolean context!
True # ^--stops here!
>>> any([])
False # gets to end, so False!

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

Доказательства all и any сокращения:

Сначала создайте noisy_iterator:

def noisy_iterator(iterable):
for i in iterable:
print('yielding ' + repr(i))
yield i

а теперь давайте просто шумно переберем списки, используя наши примеры:

>>> all(noisy_iterator([1, 2, 3, 4]))
yielding 1
yielding 2
yielding 3
yielding 4
True
>>> all(noisy_iterator([0, 1, 2, 3, 4]))
yielding 0
False

Мы видим, что all останавливается при первой логической проверке False.

And any stops on the first True boolean check:

>>> any(noisy_iterator([0, 0.0, '', (), [], {}]))
yielding 0
yielding 0.0
yielding ''
yielding ()
yielding []
yielding {}
False
>>> any(noisy_iterator([1, 0, 0.0, '', (), [], {}]))
yielding 1
True

The source

Let's look at the source to confirm the above.

Here's the source for any:

static PyObject *
builtin_any(PyObject *module, PyObject *iterable)
{
PyObject *it, *item;
PyObject *(*iternext)(PyObject *);
int cmp;

it = PyObject_GetIter(iterable);
if (it == NULL)
return NULL;
iternext = *Py_TYPE(it)->tp_iternext;

for (;;) {
item = iternext(it);
if (item == NULL)
break;
cmp = PyObject_IsTrue(item);
Py_DECREF(item);
if (cmp < 0) {
Py_DECREF(it);
return NULL;
}
if (cmp > 0) {
Py_DECREF(it);
Py_RETURN_TRUE;
}
}
Py_DECREF(it);
if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_StopIteration))
PyErr_Clear();
else
return NULL;
}
Py_RETURN_FALSE;
}

And here's the source for all:

static PyObject *
builtin_all(PyObject *module, PyObject *iterable)
{
PyObject *it, *item;
PyObject *(*iternext)(PyObject *);
int cmp;

it = PyObject_GetIter(iterable);
if (it == NULL)
return NULL;
iternext = *Py_TYPE(it)->tp_iternext;

for (;;) {
item = iternext(it);
if (item == NULL)
break;
cmp = PyObject_IsTrue(item);
Py_DECREF(item);
if (cmp < 0) {
Py_DECREF(it);
return NULL;
}
if (cmp == 0) {
Py_DECREF(it);
Py_RETURN_FALSE;
}
}
Py_DECREF(it);
if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_StopIteration))
PyErr_Clear();
else
return NULL;
}
Py_RETURN_TRUE;
}
Ответ 3

Я знаю, что это устарело, но я подумал, что было бы полезно показать, как эти функции выглядят в коде. Это действительно иллюстрирует логику, лучше, чем текст или таблица IMO. На самом деле они реализованы на C, а не на чистом Python, но они эквивалентны.

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

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

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

Когда Гвидо ван Россум (создатель Python) впервые предложил добавить any() и all(), он объяснил их, просто опубликовав в точности приведенные выше фрагменты кода.

Ответ 4

Код, о котором вы спрашиваете, взят из моего ответа, приведенного здесь. Это было предназначено для решения проблемы сравнения многобитовых массивов, то есть коллекций 1 и 0.

any и all полезны, когда вы можете положиться на "истинность" значений, то есть на их значение в логическом контексте. 1 - это True и 0 - это False удобство, которое использовал этот ответ. 5 также может быть True, поэтому, когда вы добавляете это в свои возможные входные данные... хорошо. Не работает.

Вы могли бы вместо этого сделать что-то вроде этого:

[len(set(x)) > 1 for x in zip(*d['Drd2'])]

Ему не хватает эстетики предыдущего ответа (мне действительно понравился внешний вид any(x) and not all(x)), но он выполняет свою работу.

2023-09-07 17:30 python