How do Python's any and all functions work?

后端 未结 8 1557
挽巷
挽巷 2020-11-22 01:13

I\'m trying to understand how the any() and all() Python built-in functions work.

I\'m trying to compare the tuples so that if any value i

相关标签:
8条回答
  • 2020-11-22 01:45
    >>> any([False, False, False])
    False
    >>> any([False, True, False])
    True
    >>> all([False, True, True])
    False
    >>> all([True, True, True])
    True
    
    0 讨论(0)
  • 2020-11-22 01:48

    The code in question you're asking about comes from my answer given here. It was intended to solve the problem of comparing multiple bit arrays - i.e. collections of 1 and 0.

    any and all are useful when you can rely on the "truthiness" of values - i.e. their value in a boolean context. 1 is True and 0 is False, a convenience which that answer leveraged. 5 happens to also be True, so when you mix that into your possible inputs... well. Doesn't work.

    You could instead do something like this:

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

    It lacks the aesthetics of the previous answer (I really liked the look of any(x) and not all(x)), but it gets the job done.

    0 讨论(0)
  • 2020-11-22 01:49

    How do Python's any and all functions work?

    any and all take iterables and return True if any and all (respectively) of the elements are 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
    

    If the iterables are empty, any returns False, and all returns True.

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

    I was demonstrating all and any for students in class today. They were mostly confused about the return values for empty iterables. Explaining it this way caused a lot of lightbulbs to turn on.

    Shortcutting behavior

    They, any and all, both look for a condition that allows them to stop evaluating. The first examples I gave required them to evaluate the boolean for each element in the entire list.

    (Note that list literal is not itself lazily evaluated - you could get that with an Iterator - but this is just for illustrative purposes.)

    Here's a Python implementation of any and all:

    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!
    

    Of course, the real implementations are written in C and are much more performant, but you could substitute the above and get the same results for the code in this (or any other) answer.

    all

    all checks for elements to be False (so it can return False), then it returns True if none of them were 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

    The way any works is that it checks for elements to be True (so it can return True), then it returnsFalseif 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!
    

    I think if you keep in mind the short-cutting behavior, you will intuitively understand how they work without having to reference a Truth Table.

    Evidence of all and any shortcutting:

    First, create a noisy_iterator:

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

    and now let's just iterate over the lists noisily, using our examples:

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

    We can see all stops on the first False boolean check.

    And any stops on the first True boolean check:

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

    The source

    Let's look at the source to confirm the above.

    Here's the source for 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;
    }
    

    And here's the source for 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;
    }
    
    0 讨论(0)
  • 2020-11-22 01:50

    The concept is simple:

    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 讨论(0)
  • 2020-11-22 01:52

    I know this is old, but I thought it might be helpful to show what these functions look like in code. This really illustrates the logic, better than text or a table IMO. In reality they are implemented in C rather than pure Python, but these are equivalent.

    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 particular, you can see that the result for empty iterables is just the natural result, not a special case. You can also see the short-circuiting behaviour; it would actually be more work for there not to be short-circuiting.

    When Guido van Rossum (the creator of Python) first proposed adding any() and all(), he explained them by just posting exactly the above snippets of code.

    0 讨论(0)
  • 2020-11-22 01:55
    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 .
    
    0 讨论(0)
提交回复
热议问题