ฟังก์ชันใด ๆ ของ Python ทำงานอย่างไร


225

ฉันพยายามที่จะเข้าใจว่าการทำงานของฟังก์ชั่นในตัวany()และall()Python ทำงานอย่างไร

ฉันพยายามที่จะเปรียบเทียบ tuples เพื่อว่าถ้าค่าใด ๆ ที่แตกต่างกันแล้วมันจะกลับมาและถ้าพวกเขาจะเหมือนกันทั้งหมดก็จะกลับTrue Falseพวกเขาทำงานอย่างไรในกรณีนี้เพื่อส่งคืน [เท็จ, เท็จ, เท็จ]

ddefaultdict(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 สำหรับสิ่งอันดับทั้งหมด


4
any (iterable): ส่งคืนค่า true เมื่อพบครั้งแรกของวัตถุ Truthy และส่งคืนค่า false all (iterable): ส่งคืน flase เมื่อพบครั้งแรกของวัตถุที่เป็นเท็จไม่เช่นนั้นจะคืนค่าจริง
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:กรณีตัว iterable ที่ว่างเปล่าถูกอธิบายไว้ในเอกสารอย่างเป็นทางการเช่นนี้

any

ส่งคืนTrueถ้าองค์ประกอบใด ๆ ของ iterable เป็นจริง หาก iterable ว่างเปล่าให้ส่งคืนFalse

เนื่องจากไม่มีองค์ประกอบใดที่เป็นจริงจึงส่งคืนFalseในกรณีนี้

all

ส่งคืนTrueถ้าองค์ประกอบทั้งหมดของ iterable เป็นจริง ( หรือถ้า iterable ว่างเปล่า )

เนื่องจากไม่มีองค์ประกอบใดที่เป็นเท็จจึงส่งคืน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จะพบค่า Truthy ดังนั้นมันจะส่งกลับทันทีTrueและส่วนที่เหลือmultiples_of_6จะไม่ถูกทำซ้ำ นั่นคือสิ่งที่เราเห็นเมื่อเราพิมพ์list(multiples_of_6)ผลของ7, และ89

สิ่งที่ยอดเยี่ยมนี้ถูกใช้อย่างชาญฉลาดในคำตอบนี้


ด้วยความเข้าใจพื้นฐานนี้ถ้าเราดูโค้ดของคุณคุณก็ทำได้

any(x) and not all(x)

ซึ่งทำให้แน่ใจว่าอย่างน้อยหนึ่งในค่าคือความจริง แต่ไม่ใช่ทั้งหมด [False, False, False]นั่นคือเหตุผลที่มันจะกลับมา หากคุณต้องการตรวจสอบว่าทั้งสองหมายเลขนั้นไม่เหมือนกันหรือไม่

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

@anyone: หากฉันต้องการใช้ทั้งหมด แต่กรณีที่ส่งคืน True สำหรับรายการว่างเปล่าไม่เป็นที่ยอมรับเราจะทำอย่างไร ฉันไม่เข้าใจตรรกะเบื้องหลังการให้ True ถ้ารายการว่างเปล่า ... หมายถึงทั้งหมด ([]) == True
JavaSa

1
@JavaSa คุณสามารถตรวจสอบได้อย่างชัดเจนว่ารายการว่างเปล่า ฉันเชื่อว่าสิ่งที่bool(data) and all(...)ควรทำ
thefourtheye

43

Python anyและallฟังก์ชั่นทำงานอย่างไร

any และ allใช้เวลา iterables และกลับ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

ถ้า iterables ว่างเปล่าanyผลตอบแทนFalseและallTrueผลตอบแทน

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

ฉันสาธิตallและanyสำหรับนักเรียนในชั้นเรียนวันนี้ พวกเขาส่วนใหญ่สับสนเกี่ยวกับค่าตอบแทนสำหรับ iterables ที่ว่างเปล่า การอธิบายด้วยวิธีนี้ทำให้หลอดไฟจำนวนมากเปิดใช้งาน

พฤติกรรมการลัด

พวกเขา 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 returnsเท็จ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หยุดการตรวจสอบบูลีน 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

แหล่งที่มา

ลองดูที่แหล่งที่มาเพื่อยืนยันข้างต้น

นี่คือแหล่งที่มาของ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- ฉันเพิ่มไว้ข้างต้น
Aaron Hall

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

โดยเฉพาะอย่างยิ่งคุณจะเห็นว่าผลลัพธ์สำหรับ iterables ที่ว่างเปล่าเป็นเพียงผลลัพธ์ตามธรรมชาติไม่ใช่กรณีพิเศษ คุณยังสามารถเห็นพฤติกรรมการลัดวงจร มันจะทำงานได้มากกว่าเดิมหากไม่มีการลัดวงจร

เมื่อ Guido van Rossum (ผู้สร้าง 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) ) แต่มันทำให้งานเสร็จ


อิทธิพลของฌ็องเข้าถึง CS / CE: en.wikipedia.org/wiki/Truthiness ? เรากำลังพูดถึงตรรกะคลุมเครือ? : D
Geof Sawaya

เมื่อ OP ถามว่าTrueเมื่อค่าแตกต่างกันความยาวของชุดควรเป็น 2 ไม่ใช่ 1
wombatonfire

@wombatonfire ฮ่าฮ่าจับได้ดี ฉันได้ปรับคำตอบอายุ 7 ปีของฉัน :)
roippi

คำตอบที่ดีอย่าอายุ :) วิธีการที่ดีกับชุด
wombatonfire



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 

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 .
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.