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

225

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

Я пытаюсь сравнить кортежи так, что если какое-либо значение будет другим, оно вернется, Trueа если они все одинаковые, то вернется 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 для всех кортежей?

O.rka
источник
4
any (iterable): возвращает true при первом обращении к объекту Truthy, иначе возвращает false. all (повторяемый): возвращает flase при первом обнаружении ложного объекта, иначе возвращает true.
shadow0359

Ответы:

375

Вы можете примерно представить 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

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

all

Вернуть, Trueесли все элементы итерируемого являются истинными ( или если итерируемое пусто ).

Поскольку ни один из элементов не является ложным, он возвращается 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'])]
thefourtheye
источник
@anyone: если мне нужно использовать все, кроме случая, когда он возвращает True для пустого списка, не приемлемо, что мы будем делать? Я не понимаю логику предоставления True, если список пуст ... означает все ([]) == True
JavaSa
1
@JavaSa Вы можете явно проверить, если список пуст. Я считаю, что-то вроде bool(data) and all(...)должно работать.
thefourtheye
43

Как работают 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, как искать условия , что позволяет им прекратить оценивать. Первые примеры, которые я дал, требовали, чтобы они оценивали логическое значение для каждого элемента во всем списке.

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

Вот реализация 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 returnsFalse if 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остановки на первой ложной проверке.

И anyостанавливается на первой истинной булевой проверке:

>>> 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

Источник

Давайте посмотрим на источник, чтобы подтвердить вышеизложенное.

Вот источник для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;
}

И вот источник для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;
}
Аарон Холл
источник
1
Примечание: это согласуется с математическими предикатами: «для всех» и «оно существует». Может возникнуть путаница в том, что «ДЛЯ ВСЕХ» и «ДЛЯ ЛЮБЫХ» являются синонимами в других контекстах ... en.wikipedia.org/wiki/List_of_logic_symbols
mcoolive
1
@ thanos.a это в Python/bltinmodule.c- я добавил это к вышеупомянутому.
Аарон Холл
14

Я знаю, что это старо, но я подумал, что было бы полезно показать, как эти функции выглядят в коде. Это действительно иллюстрирует логику, лучше, чем текст или таблица 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() , он объяснил их, просто разместив в точности приведенные выше фрагменты кода.

Артур Такка
источник
10

Код, о котором вы спрашиваете, взят из моего ответа, приведенного здесь . Он был предназначен для решения проблемы сравнения множественных битовых массивов - т.е. коллекций 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)), но он выполняет свою работу.

roippi
источник
Влияние Колберта достигает CS / CE: en.wikipedia.org/wiki/Truthiness ? Мы говорим о нечеткой логике? : D
Geof Sawaya
Поскольку ОП спрашивал, Trueкогда значения отличаются, длина набора должна быть 2, а не 1.
wombatonfire
@wombatonfire хаха хороший улов. Я поправил свой 7-летний ответ :)
roippi
Хорошие ответы не стареют :) Хороший подход с комплектом.
wombatonfire
7
>>> any([False, False, False])
False
>>> any([False, True, False])
True
>>> all([False, True, True])
False
>>> all([True, True, True])
True
Jobin
источник
4
s = "eFdss"
s = list(s)
all(i.islower() for i in s )   # FALSE
any(i.islower() for i in s )   # TRUE
Дэвид Глэдсон
источник
1

Концепция проста:

M =[(1, 1), (5, 6), (0, 0)]

1) print([any(x) for x in M])
[True, True, False] #only the last tuple does not have any true element

2) print([all(x) for x in M])
[True, True, False] #all elements of the last tuple are not true

3) print([not all(x) for x in M])
[False, False, True] #NOT operator applied to 2)

4) print([any(x)  and not all(x) for x in M])
[False, False, False] #AND operator applied to 1) and 3)
# if we had M =[(1, 1), (5, 6), (1, 0)], we could get [False, False, True]  in 4)
# because the last tuple satisfies both conditions: any of its elements is TRUE 
#and not all elements are TRUE 
DK250
источник
0
list = [1,1,1,0]
print(any(list)) # will return True because there is  1 or True exists
print(all(list)) # will return False because there is a 0 or False exists
return all(a % i for i in range(3, int(a ** 0.5) + 1)) # when number is divisible it will return False else return True but the whole statement is False .
Аджмал Амир
источник