Come funzionano tutte le funzioni di Python?


225

Sto cercando di capire come la any()e all()Python built-in di lavoro funzioni.

Sto cercando di confrontare le tuple in modo che se un valore è diverso, allora ritornerà Truee se saranno tutti uguali, tornerà False. Come stanno lavorando in questo caso per restituire [False, False, False]?

dè un 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]

Per quanto ne so, questo dovrebbe produrre

# [False, True, False]

poiché (1,1) sono uguali, (5,6) sono diversi e (0,0) sono uguali.

Perché sta valutando False per tutte le tuple?


4
any (iterable): restituisce true al primo incontro dell'oggetto Truthy, altrimenti restituisce false. all (iterable): restituisce flase al primo incontro dell'oggetto falsy, altrimenti restituisce true.
shadow0359

Risposte:


375

Si può approssimativamente pensare any e allcome serie di logici ore andoperatori, rispettivamente.

qualunque

anytornerà Truequando almeno uno degli elementi è Verità. Leggi i test sul valore della verità.

tutti

alltornerà Truesolo quando tutti gli elementi sono Verità.

Tabella della verità

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

Nota 1: il caso iterabile vuoto è spiegato nella documentazione ufficiale, in questo modo

any

Restituisce Truese qualche elemento dell'iterabile è vero. Se l'iterabile è vuoto, ritornaFalse

Poiché nessuno degli elementi è vero, Falsein questo caso ritorna .

all

Restituisce Truese tutti gli elementi dell'iterabile sono veri ( o se l'iterabile è vuoto ).

Poiché nessuno degli elementi è falso, Truein questo caso restituisce .


Nota 2:

Un'altra cosa importante da sapere anyed allè che metterà in corto circuito l'esecuzione, nel momento in cui conoscono il risultato. Il vantaggio è che non è necessario consumare l'intero iterabile. Per esempio,

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

Qui, (not (i % 6) for i in range(1, 10))c'è un'espressione del generatore che ritorna Truese il numero corrente tra 1 e 9 è un multiplo di 6. anyitera il multiples_of_6e quando incontra 6, trova un valore Verità, quindi ritorna immediatamente True, e il resto del multiples_of_6non è iterato. Questo è ciò che vediamo quando stampiamo list(multiples_of_6), il risultato di7 , 8e 9.

Questa cosa eccellente è usata molto abilmente in questa risposta .


Con questa comprensione di base, se osserviamo il tuo codice, lo fai

any(x) and not all(x)

il che assicura che almeno uno dei valori sia Verità ma non tutti. Ecco perché sta tornando [False, False, False]. Se vuoi davvero controllare se entrambi i numeri non sono uguali,

print [x[0] != x[1] for x in zip(*d['Drd2'])]

@anyone: se devo usare tutto tranne il caso in cui restituisca True per lista vuota non è accettabile, cosa facciamo? Non capisco la logica dietro il dare True se l'elenco è vuoto ... significa tutto ([]) == True
JavaSa

1
@JavaSa Puoi verificare esplicitamente se l'elenco è vuoto. Credo che qualcosa come bool(data) and all(...)dovrebbe funzionare.
thefourtheye il

43

Come funzionano Python anye le allfunzioni?

anye allprende iterables e restituisce Truese tutti gli elementi (rispettivamente) sono 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

Se gli iterabili sono vuoti, anyrestituisce Falsee allrestituisce True.

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

Stavo dimostrando alle anyper gli studenti in classe oggi. Erano per lo più confusi riguardo ai valori di ritorno per iterabili vuoti. Spiegarlo in questo modo ha causato l'accensione di molte lampadine.

Comportamento di scelta rapida

Essi, anye all, sia sguardo per una condizione che permette loro di smettere di valutazione. I primi esempi che ho fornito hanno richiesto loro di valutare il valore booleano per ciascun elemento dell'intero elenco.

(Nota che l'elenco letterale non è esso stesso valutato pigramente - potresti ottenerlo con un Iteratore - ma questo è solo a scopo illustrativo.)

Ecco un'implementazione Python di tutti e tutti:

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!

Ovviamente, le implementazioni reali sono scritte in C e sono molto più performanti, ma è possibile sostituire quanto sopra e ottenere gli stessi risultati per il codice in questa (o in qualsiasi altra) risposta.

all

allverifica la presenza di elementi False(in modo che possano essere restituiti False), quindi restituisce Truese nessuno di essi lo fosse 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

Il modo in cui anyfunziona è che controlla la presenza di elementi True(in modo che possa restituire 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!

Penso che se tieni presente il comportamento abbreviato, capirai intuitivamente come funzionano senza dover fare riferimento a una tabella di verità.

Prova alle anyscorciatoia:

Innanzitutto, crea un noisy_iterator:

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

e ora ripetiamo rumorosamente gli elenchi, usando i nostri esempi:

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

Possiamo vedere le allfermate sul primo controllo booleano Falso.

E si anyferma al primo vero controllo booleano:

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

La fonte

Diamo un'occhiata alla fonte per confermare quanto sopra.

Ecco la fonte perany :

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

Ed ecco la fonte perall :

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
Nota: questo è coerente con i predicati matematici: "per tutti" e "esiste". La confusione può essere che "FOR ALL" e "FOR ANY" sono sinonimi in altri contesti ... en.wikipedia.org/wiki/List_of_logic_symbols
mcoolive

1
@ thanos.a è in Python/bltinmodule.c- l'ho aggiunto a quanto sopra.
Aaron Hall

14

So che questo è vecchio, ma ho pensato che potesse essere utile mostrare come appaiono queste funzioni nel codice. Questo illustra davvero la logica, meglio del testo o di una tabella IMO. In realtà sono implementati in C piuttosto che in Python puro, ma questi sono equivalenti.

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

In particolare, puoi vedere che il risultato per gli iterabili vuoti è solo il risultato naturale, non un caso speciale. Puoi anche vedere il comportamento in corto circuito; in realtà sarebbe più lavoro per non essere in corto circuito.

Quando Guido van Rossum (il creatore di Python) per la prima volta ha proposto di aggiungere any()eall() , li spiegò semplicemente pubblicando esattamente i frammenti di codice sopra indicati.


10

Il codice in questione che stai chiedendo proviene dalla mia risposta fornita qui . Era destinato a risolvere il problema del confronto di più matrici di bit, ovvero raccolte di 1e 0.

anye allsono utili quando si può fare affidamento sulla "verità" dei valori, vale a dire il loro valore in un contesto booleano. 1 è Truee 0 è False, una comodità sfruttata da quella risposta. 5 sembra esserlo True, quindi quando lo mescoli nei tuoi possibili input ... beh. Non funziona

Potresti invece fare qualcosa del genere:

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

Manca l'estetica della risposta precedente (mi è piaciuto molto l'aspetto any(x) and not all(x)), ma fa il lavoro.


L' influenza di Colbert sta raggiungendo CS / CE: en.wikipedia.org/wiki/Truthiness ? Stiamo parlando di logica fuzzy? : D
Geof Sawaya,

Come richiesto dall'OP Truequando i valori sono diversi, la lunghezza dell'insieme dovrebbe essere 2, non 1.
wombatonfire

@wombatonfire haha ​​good catch. Ho modificato la mia risposta di 7 anni :)
roippi

Le buone risposte non invecchiano :) Bel approccio con un set.
wombatonfire

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

4
s = "eFdss"
s = list(s)
all(i.islower() for i in s )   # FALSE
any(i.islower() for i in s )   # TRUE

1

Il concetto è semplice:

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 

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 .
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.