Bagaimana cara kerja semua dan semua fungsi Python?

225

Saya mencoba memahami bagaimana fungsi bawaan any()dan all()Python bekerja.

Saya mencoba membandingkan tupel sehingga jika ada nilai yang berbeda maka akan kembali Truedan jika semuanya sama maka akan kembali False. Bagaimana mereka bekerja dalam kasus ini untuk mengembalikan [False, False, False]?

dadalah a 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]

Setahu saya, ini harus keluar

# [False, True, False]

karena (1,1) sama, (5,6) berbeda, dan (0,0) sama.

Mengapa mengevaluasi ke False untuk semua tupel?

O.rka
sumber
4
any (iterable): mengembalikan true pada pertemuan pertama objek Truthy yang lain mengembalikan false. all (iterable): mengembalikan flase pada pertemuan pertama objek falsy yang lain mengembalikan true.
shadow0359

Jawaban:

375

Secara kasar Anda dapat memikirkan anydan allsebagai serangkaian operator logis ordan andmasing-masing.

apa saja

anyakan kembali Trueketika setidaknya salah satu elemennya adalah Kebenaran. Baca tentang Pengujian Nilai Kebenaran.

semua

allakan kembali Truehanya ketika semua elemen adalah Truthy.

Meja kebenaran

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

Catatan 1: Kasing iterable kosong dijelaskan dalam dokumentasi resmi, seperti ini

any

Kembali Truejika ada elemen iterable yang benar. Jika iterable kosong, kembaliFalse

Karena tidak ada elemen yang benar, ia kembali Falsedalam kasus ini.

all

Kembali Truejika semua elemen iterable benar ( atau jika iterable kosong ).

Karena tidak ada elemen yang salah, ia kembali Truedalam kasus ini.


Catatan 2:

Hal lain yang penting untuk diketahui anydan alladalah, itu akan merusak eksekusi, saat mereka tahu hasilnya. Keuntungannya, seluruh iterable tidak perlu dikonsumsi. Sebagai contoh,

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

Di sini, (not (i % 6) for i in range(1, 10))adalah ekspresi generator yang mengembalikan Truejika angka saat ini dalam 1 dan 9 adalah kelipatan 6. anyiterates multiples_of_6dan ketika bertemu 6, ia menemukan nilai kebenaran, sehingga segera kembali True, dan sisanya multiples_of_6tidak diulang. Itulah yang kita lihat ketika kita mencetak list(multiples_of_6), hasil 7, 8dan 9.

Hal yang luar biasa ini digunakan dengan sangat cerdik dalam jawaban ini .


Dengan pemahaman dasar ini, jika kami melihat kode Anda, Anda tahu

any(x) and not all(x)

yang memastikan bahwa, setidaknya salah satu nilai adalah Kebenaran tetapi tidak semuanya. Itu sebabnya ia kembali [False, False, False]. Jika Anda benar-benar ingin memeriksa apakah kedua angkanya tidak sama,

print [x[0] != x[1] for x in zip(*d['Drd2'])]
thethourtheye
sumber
@ anyone: jika saya perlu menggunakan semua kecuali kasus di mana ia mengembalikan Benar untuk daftar kosong tidak dapat diterima, apa yang kita lakukan? Saya tidak mengerti logika di balik memberi Benar jika daftar kosong ... artinya semua ([]) == Benar
JavaSa
1
@JavaSa Anda dapat secara eksplisit memeriksa apakah daftar itu kosong. Saya percaya sesuatu seperti bool(data) and all(...)harus bekerja.
theouroureye
43

Bagaimana cara kerja Python anydan allfungsinya?

anydan allambil iterables dan kembalikan Truejika ada dan semua (masing-masing) elemen tersebut 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

Jika iterables kosong, anykembaliFalse , dan allkembali True.

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

Saya menunjukkan alldan anyuntuk siswa di kelas hari ini. Mereka sebagian besar bingung tentang nilai kembali untuk iterables kosong. Menjelaskannya dengan cara ini menyebabkan banyak bola lampu menyala.

Perilaku jalan pintas

Mereka, any dan allkeduanya mencari kondisi yang memungkinkan mereka untuk berhenti mengevaluasi. Contoh pertama yang saya berikan mengharuskan mereka untuk mengevaluasi boolean untuk setiap elemen di seluruh daftar.

(Perhatikan bahwa daftar literal tidak dengan sendirinya dievaluasi dengan malas - Anda bisa mendapatkannya dengan Iterator - tetapi ini hanya untuk tujuan ilustrasi.)

Berikut ini adalah implementasi Python dari semua dan semua:

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!

Tentu saja, implementasi nyata ditulis dalam C dan jauh lebih berkinerja, tetapi Anda bisa mengganti yang di atas dan mendapatkan hasil yang sama untuk kode dalam jawaban ini (atau yang lain).

all

allmemeriksa elemen yang akan False(sehingga dapat kembali False), lalu kembali Truejika tidak ada satu pun 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

Cara anykerjanya adalah ia memeriksa elemen yang akan True(sehingga dapat mengembalikan 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!

Saya pikir jika Anda mengingat perilaku jalan pintas, Anda akan secara intuitif memahami bagaimana mereka bekerja tanpa harus merujuk pada Tabel Kebenaran.

Bukti alldanany jalan pintas:

Pertama, buat bising_iterator:

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

dan sekarang mari kita beralih daftar dengan berisik, menggunakan contoh-contoh kami:

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

Kita bisa melihat all pemberhentian pada cek boolean False pertama.

Dan anyberhenti pada cek True boolean pertama:

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

Sumber

Mari kita lihat sumbernya untuk mengkonfirmasi hal di atas.

Inilah sumber untukany :

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

Dan inilah sumber untukall :

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
sumber
1
Catatan: ini konsisten dengan predikat matematika: "untuk semua" dan "ada". Kebingungan bisa jadi bahwa "UNTUK SEMUA" dan "UNTUK SETIAP" adalah sinonim dalam konteks lain ... en.wikipedia.org/wiki/List_of_logic_symbols
mcoolive
1
@ thanos.a ada di Python/bltinmodule.c- saya menambahkannya di atas.
Aaron Hall
14

Saya tahu ini sudah tua, tapi saya pikir mungkin membantu untuk menunjukkan seperti apa fungsi-fungsi ini dalam kode. Ini benar-benar menggambarkan logika, lebih baik daripada teks atau tabel IMO. Pada kenyataannya mereka diimplementasikan dalam C daripada Python murni, tetapi ini setara.

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

Secara khusus, Anda dapat melihat bahwa hasil untuk iterables kosong hanyalah hasil alami, bukan kasus khusus. Anda juga dapat melihat perilaku hubungan arus pendek; sebenarnya akan lebih banyak pekerjaan agar tidak terjadi hubungan arus pendek.

Ketika Guido van Rossum (pencipta Python) pertama kali mengusulkan penambahan any()danall() , ia menjelaskannya hanya dengan memposting potongan kode di atas.

Arthur Tacca
sumber
10

Kode yang Anda tanyakan berasal dari jawaban saya yang diberikan di sini . Itu dimaksudkan untuk memecahkan masalah membandingkan beberapa bit array - yaitu koleksi 1dan 0.

anydan allberguna ketika Anda dapat mengandalkan "kebenaran" nilai - yaitu nilainya dalam konteks boolean. 1 adalah Truedan 0 adalah False, kenyamanan yang dijawab oleh leveraged. 5 kebetulan juga True, jadi ketika Anda mencampurnya ke dalam input yang mungkin Anda ... yah. Tidak bekerja

Anda bisa melakukan sesuatu seperti ini:

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

Itu tidak memiliki estetika dari jawaban sebelumnya (saya sangat suka tampilan any(x) and not all(x)), tetapi menyelesaikan pekerjaan.

roippi
sumber
Pengaruh Colbert mencapai CS / CE: en.wikipedia.org/wiki/Truthiness ? Apakah kita berbicara logika fuzzy? : D
Geof Sawaya
Ketika OP menanyakan Truekapan nilainya berbeda, panjang set harus 2, bukan 1.
wombatonfire
@ombatonfire haha ​​tangkapan yang bagus. Saya telah menyesuaikan jawaban 7 tahun saya :)
roippi
Jawaban yang bagus jangan umur :) Pendekatan yang bagus dengan satu set.
wombatonfire
7
>>> any([False, False, False])
False
>>> any([False, True, False])
True
>>> all([False, True, True])
False
>>> all([True, True, True])
True
Jobin
sumber
4
s = "eFdss"
s = list(s)
all(i.islower() for i in s )   # FALSE
any(i.islower() for i in s )   # TRUE
David Gladson
sumber
1

Konsepnya sederhana:

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