Jak działają wszystkie i wszystkie funkcje Pythona?

225

Próbuję zrozumieć, jak działają funkcje wbudowane any()i all()Python.

Próbuję porównać krotki, aby jeśli jakakolwiek wartość była inna, to ona zwróci Truei jeśli wszystkie są takie same, zwróci False. Jak w tej sprawie pracują nad zwrotem [Fałsz, Fałsz, Fałsz]?

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

O ile mi wiadomo, powinno to dać wynik

# [False, True, False]

ponieważ (1,1) są takie same, (5,6) są różne, a (0,0) są takie same.

Dlaczego dla wszystkich krotek ma wartość False?

O.rka
źródło
4
any (iterable): zwraca true przy pierwszym spotkaniu z obiektem Truthy, w przeciwnym razie zwraca false. all (iterable): zwraca flase przy pierwszym spotkaniu z obiektem falsy, w przeciwnym razie zwraca true.
shadow0359

Odpowiedzi:

375

Można z grubsza myśleć anyi alljak seria logicznych ori andoperatorów, odpowiednio.

każdy

anypowróci, Truegdy co najmniej jeden z elementów jest Prawdą. Przeczytaj o testowaniu wartości prawdy.

wszystko

allpowróci Truetylko wtedy, gdy wszystkie elementy są Prawdą.

Tabela prawdy

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

Uwaga 1: Pusta iterowalna sprawa jest wyjaśniona w oficjalnej dokumentacji, tak jak to

any

Zwraca, Truejeśli dowolny element iterowalny jest prawdziwy. Jeśli iteracja jest pusta, wróćFalse

Ponieważ żaden z elementów nie jest prawdziwy, zwraca się Falsew tym przypadku.

all

Zwraca, Truejeśli wszystkie elementy iterowalne są prawdziwe ( lub jeśli iterowalne jest puste ).

Ponieważ żaden z elementów nie jest fałszywy, Truew tym przypadku zwraca wartość .


Uwaga 2:

Kolejną ważną rzeczą, aby wiedzieć anyi allto, że będzie zwarcie wykonanie, moment znają wynik. Zaletą jest to, że nie trzeba zużywać całej iteracji. Na przykład,

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

Tutaj (not (i % 6) for i in range(1, 10))jest wyrażenie generator, który powraca Truejeśli obecna liczba w ciągu 1 do 9 jest wielokrotnością 6. anyiteruje multiples_of_6a kiedy spotyka 6, to znajdzie wartość Truthy, więc natychmiast wraca True, a reszta multiples_of_6nie powtórzyć. To, co widzimy, kiedy drukować list(multiples_of_6), wynik 7, 8i 9.

Ta doskonała rzecz została wykorzystana bardzo sprytnie w tej odpowiedzi .


Z tym podstawowym zrozumieniem, jeśli spojrzymy na twój kod, robisz to

any(x) and not all(x)

co zapewnia, że ​​przynajmniej jedna z wartości jest Prawda, ale nie wszystkie. Właśnie dlatego powraca [False, False, False]. Jeśli naprawdę chcesz sprawdzić, czy obie liczby nie są takie same,

print [x[0] != x[1] for x in zip(*d['Drd2'])]
thefourtheye
źródło
@ każdy: jeśli muszę użyć wszystkich oprócz przypadku, w którym zwraca wartość Prawda dla pustej listy jest niedopuszczalna, co robimy? Nie rozumiem logiki podania wartości True, jeśli lista jest pusta ... co oznacza wszystko ([]) == True
JavaSa
1
@JavaSa Możesz jawnie sprawdzić, czy lista jest pusta. Uważam, że coś takiego bool(data) and all(...)powinno działać.
theourourhehe
43

Jak działają Python anyi allfunkcje?

anyi allweź iterable i zwróć, Truejeśli są jakieś i wszystkie (odpowiednio) elementy 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

Jeśli iteracje są puste, anyzwraca Falsei allzwraca True.

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

Demonstrowałem dzisiaj alli anydla uczniów w klasie. Byli w większości zdezorientowani co do wartości zwracanych dla pustych iteracji. Wyjaśnienie tego w ten sposób spowodowało włączenie wielu żarówek.

Skrótowe zachowanie

Oni, anyi allzarówno spojrzenie na chorobę, która pozwala im przestać oceny. Pierwsze przykłady, które podałem, wymagały od nich oceny wartości logicznej dla każdego elementu na całej liście.

(Zauważ, że literał listy sam w sobie nie jest leniwie oceniany - można to uzyskać za pomocą Iteratora - ale służy to wyłącznie celom ilustracyjnym).

Oto implementacja Pythona dla wszystkich:

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!

Oczywiście rzeczywiste implementacje są napisane w C i są znacznie wydajniejsze, ale możesz zastąpić powyższe i uzyskać te same wyniki dla kodu w tej (lub innej) odpowiedzi.

all

allsprawdza, czy elementy mają być False(aby mógł zwrócić False), a następnie zwraca, Truejeśli żaden z nich nie był 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

Sposób anydziałania polega na tym, że sprawdza, czy istnieją elementy True(aby mógł zwrócić 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!

Myślę, że jeśli weźmiesz pod uwagę krótkie zachowanie, intuicyjnie zrozumiesz, jak one działają, bez konieczności odwoływania się do Tabeli Prawdy.

Dowody alli anyskróty:

Najpierw utwórz noisy_iterator:

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

a teraz przejdźmy głośno do list, korzystając z naszych przykładów:

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

Widzimy allzatrzymania na pierwszym fałszywym czeku logicznym.

I anyzatrzymuje się przy pierwszym teście logicznym True:

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

Źródło

Spójrzmy na źródło, aby potwierdzić powyższe.

Oto źródłoany :

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

A oto źródłoall :

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;
}
Aaron Hall
źródło
1
Uwaga: jest to zgodne z predykatami matematycznymi: „dla wszystkich” i „istnieje”. Pomieszanie może polegać na tym, że „FOR ALL” i „FOR ANY” są synonimami w innych kontekstach ... en.wikipedia.org/wiki/List_of_logic_symbols
mcoolive
1
@ thanos.a jest w środku Python/bltinmodule.c- dodałem go do powyższego.
Aaron Hall
14

Wiem, że to stare, ale pomyślałem, że pomocne może być pokazanie, jak te funkcje wyglądają w kodzie. To naprawdę ilustruje logikę, lepszą niż tekst lub tabela IMO. W rzeczywistości są one implementowane w języku C zamiast w czystym Pythonie, ale są one równoważne.

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

W szczególności widać, że wynik dla pustych iteracji jest tylko wynikiem naturalnym, a nie szczególnym przypadkiem. Możesz również zobaczyć zachowanie zwarciowe; byłoby więcej pracy, żeby nie doszło do zwarcia.

Kiedy Guido van Rossum (twórca Pythona) po raz pierwszy zaproponował dodanie any()iall() wyjaśnił je, zamieszczając dokładnie powyższe fragmenty kodu.

Arthur Tacca
źródło
10

Kod, o który pytasz, pochodzi z mojej odpowiedzi podanej tutaj . Miało to rozwiązać problem porównywania wielu tablic bitowych - tj. Kolekcji 1i 0.

anyi allsą przydatne, gdy można polegać na „prawdziwości” wartości - tj. ich wartości w kontekście logicznym. 1 oznacza, Truea 0 oznacza Falsewygodę, którą wykorzystała ta odpowiedź. Zdarza się też, że 5 True, więc kiedy to połączysz z możliwymi wejściami ... no cóż. Nie działa

Zamiast tego możesz zrobić coś takiego:

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

Brakuje mu estetyki poprzedniej odpowiedzi ( naprawdę podobał mi się wygląd any(x) and not all(x)), ale wykonuje zadanie.

roippi
źródło
Wpływ Colberta dociera do CS / CE: en.wikipedia.org/wiki/Truthiness ? Czy mówimy o logice rozmytej? : D
Geof Sawaya
Gdy OP zapytał, Truekiedy wartości są różne, długość zestawu powinna wynosić 2, a nie 1.
wombatonfire
@wombatonfire haha ​​good catch.
Poprawiłem
Dobre odpowiedzi nie starzeją się :) Ładne podejście z zestawem.
wombatonfire
7
>>> any([False, False, False])
False
>>> any([False, True, False])
True
>>> all([False, True, True])
False
>>> all([True, True, True])
True
Praca w
źródło
4
s = "eFdss"
s = list(s)
all(i.islower() for i in s )   # FALSE
any(i.islower() for i in s )   # TRUE
David Gladson
źródło
1

Pomysł jest prosty:

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
źródło
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 .
Ajmal Aamir
źródło