How does this input work with the Python 'any' function?
Question:
In the python docs page for any
, the equivalent code for the any()
function is given as:
def any(iterable):
for element in iterable:
if element:
return True
return False
How does this function know what element I wanna test if call it in this form?
any(x > 0 for x in list)
From the function definition, all I can see is that I’m passing an iterable object. How does the for
loop know I am looking for something > 0
?
Answers:
It’s because the iterable is
(x > 0 for x in list)
Note that x > 0
returns either True
or False
and thus you have an iterable of booleans.
(x > 0 for x in list)
in that function call creates a generator expression eg.
>>> nums = [1, 2, -1, 9, -5]
>>> genexp = (x > 0 for x in nums)
>>> for x in genexp:
print x
True
True
False
True
False
Which any
uses, and shortcircuits on encountering the first object that evaluates True
If you use any(lst)
you see that lst
is the iterable, which is a list of some items. If it contained [0, False, '', 0.0, [], {}, None]
(which all have boolean values of False
) then any(lst)
would be False
. If lst
also contained any of the following [-1, True, "X", 0.00001]
(all of which evaluate to True
) then any(lst)
would be True
.
In the code you posted, x > 0 for x in lst
, this is a different kind of iterable, called a generator expression. Before generator expressions were added to Python, you would have created a list comprehension, which looks very similar, but with surrounding []
‘s: [x > 0 for x in lst]
. From the lst
containing [-1, -2, 10, -4, 20]
, you would get this comprehended list: [False, False, True, False, True]
. This internal value would then get passed to the any
function, which would return True
, since there is at least one True
value.
But with generator expressions, Python no longer has to create that internal list of True(s)
and False(s)
, the values will be generated as the any
function iterates through the values generated one at a time by the generator expression. And, since any
short-circuits, it will stop iterating as soon as it sees the first True
value. This would be especially handy if you created lst
using something like lst = range(-1,int(1e9))
(or xrange
if you are using Python2.x). Even though this expression will generate over a billion entries, any
only has to go as far as the third entry when it gets to 1
, which evaluates True
for x>0
, and so any
can return True
.
If you had created a list comprehension, Python would first have had to create the billion-element list in memory, and then pass that to any
. But by using a generator expression, you can have Python’s builtin functions like any
and all
break out early, as soon as a True
or False
value is seen.
Simply saying, any() does this work : according to the condition even if it encounters one fulfilling value in the list, it returns true, else it returns false.
list = [2,-3,-4,5,6]
a = any(x>0 for x in lst)
print a:
True
list = [2,3,4,5,6,7]
a = any(x<0 for x in lst)
print a:
False
>>> names = ['King', 'Queen', 'Joker']
>>> any(n in 'King and john' for n in names)
True
>>> all(n in 'King and Queen' for n in names)
False
It just reduce several line of code into one.
You don’t have to write lengthy code like:
for n in names:
if n in 'King and john':
print True
else:
print False
In the python docs page for any
, the equivalent code for the any()
function is given as:
def any(iterable):
for element in iterable:
if element:
return True
return False
How does this function know what element I wanna test if call it in this form?
any(x > 0 for x in list)
From the function definition, all I can see is that I’m passing an iterable object. How does the for
loop know I am looking for something > 0
?
It’s because the iterable is
(x > 0 for x in list)
Note that x > 0
returns either True
or False
and thus you have an iterable of booleans.
(x > 0 for x in list)
in that function call creates a generator expression eg.
>>> nums = [1, 2, -1, 9, -5]
>>> genexp = (x > 0 for x in nums)
>>> for x in genexp:
print x
True
True
False
True
False
Which any
uses, and shortcircuits on encountering the first object that evaluates True
If you use any(lst)
you see that lst
is the iterable, which is a list of some items. If it contained [0, False, '', 0.0, [], {}, None]
(which all have boolean values of False
) then any(lst)
would be False
. If lst
also contained any of the following [-1, True, "X", 0.00001]
(all of which evaluate to True
) then any(lst)
would be True
.
In the code you posted, x > 0 for x in lst
, this is a different kind of iterable, called a generator expression. Before generator expressions were added to Python, you would have created a list comprehension, which looks very similar, but with surrounding []
‘s: [x > 0 for x in lst]
. From the lst
containing [-1, -2, 10, -4, 20]
, you would get this comprehended list: [False, False, True, False, True]
. This internal value would then get passed to the any
function, which would return True
, since there is at least one True
value.
But with generator expressions, Python no longer has to create that internal list of True(s)
and False(s)
, the values will be generated as the any
function iterates through the values generated one at a time by the generator expression. And, since any
short-circuits, it will stop iterating as soon as it sees the first True
value. This would be especially handy if you created lst
using something like lst = range(-1,int(1e9))
(or xrange
if you are using Python2.x). Even though this expression will generate over a billion entries, any
only has to go as far as the third entry when it gets to 1
, which evaluates True
for x>0
, and so any
can return True
.
If you had created a list comprehension, Python would first have had to create the billion-element list in memory, and then pass that to any
. But by using a generator expression, you can have Python’s builtin functions like any
and all
break out early, as soon as a True
or False
value is seen.
Simply saying, any() does this work : according to the condition even if it encounters one fulfilling value in the list, it returns true, else it returns false.
list = [2,-3,-4,5,6]
a = any(x>0 for x in lst)
print a:
True
list = [2,3,4,5,6,7]
a = any(x<0 for x in lst)
print a:
False
>>> names = ['King', 'Queen', 'Joker']
>>> any(n in 'King and john' for n in names)
True
>>> all(n in 'King and Queen' for n in names)
False
It just reduce several line of code into one.
You don’t have to write lengthy code like:
for n in names:
if n in 'King and john':
print True
else:
print False