Làm thế nào để Python và bất kỳ chức năng nào hoạt động?


225

Tôi đang cố gắng hiểu cách các hàm tích hợp any()all()Python hoạt động.

Tôi đang cố gắng so sánh các bộ dữ liệu để nếu bất kỳ giá trị nào khác nhau thì nó sẽ trả về Truevà nếu tất cả chúng đều giống nhau thì nó sẽ trả về False. Làm thế nào họ làm việc trong trường hợp này để trả về [Sai, Sai, Sai]?

dlà một 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]

Theo hiểu biết của tôi, điều này sẽ xuất ra

# [False, True, False]

vì (1,1) giống nhau, (5,6) khác nhau và (0,0) giống nhau.

Tại sao nó được đánh giá là Sai cho tất cả các bộ dữ liệu?


4
any (iterable): trả về true trong lần gặp đầu tiên của đối tượng Truthy khác trả về false. all (iterable): trả về flase trong lần gặp đầu tiên của đối tượng giả mạo khác trả về true.
bóng0359

Câu trả lời:


375

Bạn có thể nghĩ đại khái anyallnhư một loạt các toán tử orandtoán tử, tương ứng.

bất kì

anysẽ trở lại Truekhi có ít nhất một trong các yếu tố là Truthy. Đọc về Kiểm tra giá trị thật.

tất cả

allsẽ Truechỉ trở lại khi tất cả các yếu tố là Chân lý.

Bảng chân lý

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

Lưu ý 1: Trường hợp lặp lại trống được giải thích trong tài liệu chính thức, như thế này

any

Trả về Truenếu bất kỳ phần tử nào của lần lặp là đúng. Nếu iterable trống, quay trở lạiFalse

Vì không có yếu tố nào là đúng, nên nó trả về Falsetrong trường hợp này.

all

Trả về Truenếu tất cả các phần tử của iterable là đúng ( hoặc nếu iterable trống ).

Vì không có phần tử nào là sai, nó trả về Truetrong trường hợp này.


Lưu ý 2:

Một điều quan trọng khác cần biết anyalllà, nó sẽ làm ngắn mạch việc thực hiện, thời điểm họ biết kết quả. Ưu điểm là, toàn bộ nhu cầu lặp lại không được tiêu thụ. Ví dụ,

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

Ở đây, (not (i % 6) for i in range(1, 10))là một biểu thức trình tạo trả về Truenếu số hiện tại trong 1 và 9 là bội số của 6. anylặp lại multiples_of_6và khi nó gặp nhau 6, nó tìm thấy một giá trị Truthy, vì vậy nó trả về ngay lập tức Truevà phần còn lại multiples_of_6không bị lặp lại. Đó là những gì chúng ta thấy khi chúng ta in list(multiples_of_6), kết quả của 7, 89.

Điều tuyệt vời này được sử dụng rất thông minh trong câu trả lời này .


Với sự hiểu biết cơ bản này, nếu chúng tôi xem mã của bạn, bạn sẽ làm

any(x) and not all(x)

điều chắc chắn rằng, ít nhất một trong những giá trị là Sự thật nhưng không phải tất cả chúng. Đó là lý do tại sao nó trở lại [False, False, False]. Nếu bạn thực sự muốn kiểm tra xem cả hai số này có giống nhau không,

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

@anyone: nếu tôi cần sử dụng tất cả nhưng trường hợp nó trả về True cho danh sách trống thì không được chấp nhận, chúng tôi phải làm gì? Tôi không hiểu logic đằng sau việc đưa ra True nếu danh sách trống ... có nghĩa là tất cả ([]) == True
JavaSa

1
@JavaSa Bạn có thể kiểm tra rõ ràng nếu danh sách trống. Tôi tin rằng một cái gì đó như bool(data) and all(...)nên làm việc.
thefourtheye

43

Làm thế nào để Python anyvà các allchức năng hoạt động?

anyalllấy iterables và trả về Truenếu có và tất cả (tương ứng) các phần tử 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

Nếu các lần lặp trống, anytrả về Falsealltrả về True.

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

Tôi đã chứng minh allanycho các sinh viên trong lớp ngày hôm nay. Họ chủ yếu nhầm lẫn về các giá trị trả về cho các lần lặp trống. Giải thích theo cách này khiến rất nhiều bóng đèn bật lên.

Hành vi cắt ngắn

Họ, anyall, cả hai đều tìm kiếm một điều kiện cho phép họ ngừng đánh giá. Các ví dụ đầu tiên tôi đưa ra yêu cầu họ đánh giá boolean cho từng phần tử trong toàn bộ danh sách.

(Lưu ý rằng danh sách theo nghĩa đen không được đánh giá một cách lười biếng - bạn có thể nhận được điều đó với Iterator - nhưng đây chỉ là mục đích minh họa.)

Đây là một triển khai Python của bất kỳ và tất cả:

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!

Tất nhiên, các triển khai thực tế được viết bằng C và có hiệu suất cao hơn nhiều, nhưng bạn có thể thay thế ở trên và nhận được kết quả tương tự cho mã trong câu trả lời này (hoặc bất kỳ khác).

all

allkiểm tra các phần tử được False(để nó có thể trả về False), sau đó nó trả về Truenếu không có phần tử nào trong số chúng 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

Cách thức anyhoạt động là nó kiểm tra các phần tử trở thành True(để nó có thể trả về True), then it returnsSai 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!

Tôi nghĩ rằng nếu bạn ghi nhớ hành vi cắt ngắn, bạn sẽ trực giác hiểu cách chúng hoạt động mà không cần phải tham khảo Bảng chân lý.

Bằng chứng allanyrút gọn:

Đầu tiên, tạo một nhiễu_iterator:

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

và bây giờ chúng ta hãy lặp đi lặp lại các danh sách một cách ồn ào, bằng cách sử dụng các ví dụ của chúng tô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

Chúng ta có thể thấy các allđiểm dừng trên kiểm tra boolean Sai đầu tiên.

anydừng lại ở lần kiểm tra boolean True đầu tiên:

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

Nguồn

Hãy nhìn vào nguồn để xác nhận ở trên.

Đây là nguồn choany :

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

Và đây là nguồn choall :

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
Lưu ý: điều này phù hợp với các vị từ toán học: "cho tất cả" và "nó tồn tại". Sự nhầm lẫn có thể là "CHO ​​TẤT CẢ" và "CHO ​​BẤT CỨ" là từ đồng nghĩa trong các bối cảnh khác ... en.wikipedia.org/wiki/List_of_logic_symbols
mcoolive

1
@ thanos.a nó vào Python/bltinmodule.c- Tôi đã thêm nó vào ở trên.
Aaron Hall

14

Tôi biết điều này đã cũ, nhưng tôi nghĩ nó có thể hữu ích để hiển thị các hàm này trông như thế nào trong mã. Điều này thực sự minh họa logic, tốt hơn so với văn bản hoặc bảng IMO. Trong thực tế, chúng được thực hiện bằng C chứ không phải Python thuần túy, nhưng chúng tương đương nhau.

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

Cụ thể, bạn có thể thấy rằng kết quả cho các lần lặp trống chỉ là kết quả tự nhiên, không phải là trường hợp đặc biệt. Bạn cũng có thể thấy hành vi ngắn mạch; nó thực sự sẽ làm việc nhiều hơn để không bị đoản mạch.

Khi Guido van Rossum (người tạo ra Python) lần đầu tiên đề xuất thêm any()all() , ông đã giải thích chúng bằng cách chỉ đăng chính xác các đoạn mã trên.


10

Mã trong câu hỏi bạn đang hỏi về xuất phát từ câu trả lời của tôi được đưa ra ở đây . Nó được dự định để giải quyết vấn đề so sánh nhiều mảng bit - tức là các tập hợp của 10.

anyallrất hữu ích khi bạn có thể dựa vào "tính trung thực" của các giá trị - tức là giá trị của chúng trong bối cảnh boolean. 1 là Truevà 0 là False, một sự thuận tiện mà câu trả lời tận dụng. 5 cũng xảy ra True, vì vậy khi bạn trộn nó vào đầu vào có thể của bạn ... tốt. Không hoạt động.

Thay vào đó, bạn có thể làm một cái gì đó như thế này:

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

Nó thiếu tính thẩm mỹ của câu trả lời trước (tôi thực sự thích vẻ ngoài của nó any(x) and not all(x)), nhưng nó hoàn thành công việc.


Ảnh hưởng của Colbert đang đạt đến CS / CE: en.wikipedia.org/wiki/Truthiness ? Có phải chúng ta đang nói logic mờ? : D
Geof Sawaya

Như OP đã yêu cầu Truekhi các giá trị khác nhau, độ dài của tập hợp phải là 2, không phải 1.
wombatonfire

@wombatonfire haha ​​bắt tốt. Tôi đã điều chỉnh câu trả lời 7 năm tuổi của mình :)
roippi

Câu trả lời tốt không tuổi :) Cách tiếp cận tốt đẹp với một bộ.
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

Khái niệm này là đơn giản:

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 .
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.