I am new to Python and was playing with it until I have a problem with any() function. According to the Python library, the code for it is:
def any(iterable):
for element in iterable:
if element:
return True
return False
I created a list: list = [-1, 1] and I expected:
print any(list) < 0
print any(x < 0 for x in list)
would print two True's and the two statements are equivalent. But instead Python printed
False
True
Why is the first statement False? How is it different from the second one?
any(list) returns a boolean value, based only on the contents of list. Both -1 and 1 are true values (they are not numeric 0), so any() returns True:
>>> lst = [1, -1]
>>> any(lst)
True
Boolean values in Python are a subclass of int, where True == 1 and False == 0, so True is not smaller than 0:
>>> True < 0
False
The statement any(list) is in no way equivalent to any(x < 0 for x in list) here. That expression uses a generator expression to test each element individually against 0, and there is indeed one value smaller than 0 in that list, -1:
>>> (x < 0 for x in lst)
<generator object <genexpr> at 0x1077769d8>
>>> list(x < 0 for x in lst)
[False, True]
so any() returns True as soon as it encounters the second value in the sequence produced.
Note: You should avoid using list as a variable name as that masks the built-in type. I used lst in my answer instead, so that I could use the list() callable to illustrate what the generator expression produces.
As stated in the docs, any(list) returns a boolean. You're comparing that boolean to the integer 0:
>>> any(list)
True
>>> True < 0
False
Related
I am trying to convert a list of lists into a single list with '1's if any of the elements in a single list is 1 and 0 otherwise. I have the following list:
result =[[-1, -1, 0], [1, 0, -1], [1, 1, 0]]
and if I use any() on the first list
i.e. result[0], I get True even though it is supposed to be false. any(result[0]) gives True.
However, when I test each element separately, I get False in each case
i.e. result[0][0] == True gives False and similar result for the remaining elements. I can't seem to understand what I'm doing wrong.
any tests if any value is truthy, not if any value equals True. All non-zero integers are truthy so any([-1, -1, 0]) is True.
See for details Truth Value Testing which applies to any and all as well.
First, why your attempts didn't work:
bool(X) = True if x != 0; else False.
Then any(result[0]) will return True, as there is at least one non-zero element in the list.
Your second test result[0][0] == True cannot work, as result[0][0] = -1, then not True (Not even boolean in fact). So it returns False.
To do what you want, you can use any with list comprehension:
result = [1 if any(y == 1 for y in x) else 0 for x in result]
>>> [0, 1, 1] For your example
EDIT:
According to Kelly Bundy's comment, another way to do it:
result = [1 if 1 in x else 0 for x in result]
You can also use boolean, but you only can reach True/False (or 1/0)
This is the task:
Write an algorithm that takes an array and moves all of the zeros to the end, preserving the order of the other elements
What is wrong with this code? Why is it not keeping boolean values while iterating through the list and removing zeros? Is it because False is equal to 0?
move_zeros([False,1,2,0,1,0,1,0,3,0,1])
def move_zeros(array):
count=0
for num in array:
if num == 0:
count +=1
array.remove(0)
return array +[0]*count
Yes, False == 0 will evaluate to True in Python which is why False values are being removed from your array.
In Python, True and False are implemented as singletons, meaning all False values point to the same instance. Therefore, you can use the is operator to check if a value is exactly equal to this singleton.
False is 0 will return False, while False == 0 will return True.
x = len(lis)
y = []
for i in range(len(lis)):
if lis[i]!=0:
y.append(lis[i])
if len(y)!=len(lis):
z = len(lis)-len(y)
for i in range(z):
y.append(0)
Seems like its a homework problem. Happy to help tho.
Edit: use print(y) and you'll get what you want
Yes, indeed False == 0. Actually, bool is a subtype of int. If you want to strictly compare if False is equal to 0, then another comparison should be added to the if statement.
Also, do not modify a list while you are iterating over itself. Create a new one instead.
def move_zeros(list_):
result = []
zeros = 0
for item in list_:
if item == 0 and type(item) == int:
zeros += 1
continue
result.append(item)
return result + [0] * zeros
Yes 0 evaluates to False and 1 evaluates to True, use this
def move_zeros(obj):
new_list = []
zeros_list = []
for item in obj:
if item != 0 or is False:
new_list.append(item)
else:
zeros_list.append(item)
new_list.extend(zero_list)
return new_list
This adds all non 0 to one list and all 0's to another, then returns the new_list after iterating over the zeros_list and adding them to the end of the new_list
There are 2 issues in your code:
You directly changed the list over which you iterate — it is always dangerous.
Other answers explained to you why False == 0 is True.
I made as few changes in your code as it was possible to fix these issues:
I created a new, empty array, and instead of removing “bad” elements from the original list, I appended the “good” ones to that new array.
I tested a current element for its type, too.
def move_zeros(array):
count=0
new_array = []
for num in array:
if num == 0 and type(num) is int:
count +=1
else:
new_array.append(num)
return new_array + [0]*count
Test:
move_zeros([False,1,2,0,1,0,1,0,3,0,1])
[False, 1, 2, 1, 1, 3, 1, 0, 0, 0, 0]
Looking to understand the meaning of bool on a generator expression in python.
bool(x for x in []) yields True
bool(x for x in [1, 2, 3]) yields True
bool(range(0)) yields False (??)
bool(range(3)) yields True
The confusion arises from range not returning a generator.
In general generators are just objects and therefore are always truthy (as opposed to containers which are False when empty).
If you do type(range(0)) you get "range", but it's not a generator, and apparently has an implicit truth value when it is empty vs non empty.
bool returns true for 'truthy' values and false for 'falsy' values.
Case 1:
(x for x in [])
Creates a generator object.
Ouput:
<generator object <genexpr> at 0x03DCDEF0>
Since an object is generated, its Truthy and it returns True.
Case 2:
(x for x in [1, 2, 3])
Same as above
Case 3:
(range(0))
This is just range(0, 0).
Try this:
for i in range(0): print(i)
There will be no output.
You will not get any value, which is Falsy and False is returned.
Case 4:
(range(3))
Try this:
for i in range(3): print(i)
Ouput:
0
1
2
Values are returned which means its truthy and True is returned.
More on Truth Value Testing
I was doing coderbyte's Python Array Addition I challenge, but I couldn't get it quite right. I saw another user's correct code, and I'm kind of puzzled by it. Mainly, what does "or" do in a return statement? It's preventing me from fully understanding the solution to this problem. Thanks.
The question is as follows:
Have the function ArrayAdditionI(arr) take the array of numbers stored in arr and return the string true if any combination of numbers in the array can be added up to equal the largest number in the array, otherwise return the string false. For example: if arr contains [4, 6, 23, 10, 1, 3] the output should return true because 4 + 6 + 10 + 3 = 23. The array will not be empty, will not contain all the same elements, and may contain negative numbers.
def subsetsum(target, arr):
if len(arr) == 0:
return target == 0
return subsetsum(target, arr[1:]) or subsetsum(target - arr[0], arr[1:])
def ArrayAdditionI(arr):
arr = sorted(arr)
target = arr[-1]
arr = arr[:-1]
return 'true' if subsetsum(target, arr) else 'false'
# keep this function call here
# to see how to enter arguments in Python scroll down
print ArrayAdditionI(raw_input())
Here's how to break this down:
return subsetsum(target, arr[1:]) or subsetsum(target - arr[0], arr[1:])
This has the form return a or b where a = subsetsum(target, arr[1:]) and b = subsetsum(target - arr[0], arr[1:]).
If bool(a) is True, then the expression a or b short circuits and returns whatever the value of a is.
If bool(a) is False, then b must be evaluated to determine the value of the expression a or b.
Thus, return a or b is shorthand for the following, with the benefit that b is not evaluated (if it's a function) if bool(a) is True, thanks to short-circuiting logic.
if bool(a):
return a
else:
return b
It's not doing anything special in the context of "return", so that's kind of confusing. Take away return and just look at a boolean expression of
False or True
Will evaluate to True because one of the statements evaluates to True. The example with return is just taking the result of evaluating the boolean expression and returning it. So True if any of the subsetsum() calls return True, otherwise False.
>>> False or True
True
>>> False or False
False
I was testing a list to see if it's empty or not. Normally I use len(list) == 0 and I vaguely remembered reading a little while ago that the correct way to test if a list is empty was whether it was True or false.
So I tried list is False, and that returned False. Maybe I'm suppose to be using == ?
Nope, that also returned false. list is True, returned false as did list == True.
Now I'm confused so I do a quick google and end up at: Best way to check if a list is empty
The top answer is:
if not a:
print "List is empty"
So I search around some more and end up in the python manual where 4.1 states:
Any object can be tested for truth value, for use in an if or while condition or as operand of the Boolean operations below. The following values are considered false:
any empty sequence, for example, '', (), [].
Now I'm plain confused. If I test a list as if not list, it works fine. But if an empty list is false, then why can't I just do if list is False or if list == False?
Thanks
An empty list is not False, but when you convert it to a boolean, it converts to False. Likewise for dicts, tuples, strings, etc.:
>>> [] == False
False
>>> bool([]) == False
True
>>> {} == False
False
>>> bool({}) == False
True
When you put something in the condition of an if clause, it is its boolean value that is used for testing the if. That's why if someList is the same as if bool(someList). Likewise, not foo does a boolean not, so not [] equals True.
As other have said, in python bool([]) == False. One thing that is frequently exploited by python programmers is that the operators and and or don't (necessarily) return True/False. Consider the following:
3 and 4 #returns 4
0 and 8 #returns 0 -- This is short-circuit evaluation
0 or 8 #returns 8
True or 0 #returns True -- This is short-circuit evaluation
[] or False #returns False
False or [] #returns []
What happens in an if statement is that the condition gets evaluated as above and then python implicitly calls bool on the result -- So you can think of it as:
if condition:
is the same thing as:
if bool(condition):
as far as python is concerned. Similarly for the not operator:
not condition
is the same thing as
not bool(condition)
mylist is False means "is the object named mylist exactly the same object as False?"
mylist == False means "is the object named mylist equal to False?
not mylist means "does the object named mylist behave falsily?
None of these are equivalent: 1 is not 1.0 but 1 == 1.0 and [] != False but not [] is True.
Comparing the list to False, and testing the list's truth or falsehood aren't quite the same thing. An empty list isn't equal to False, but behaves as False in a boolean context.
Here's another way to say it that might help this make sense:
print (bool([]) == False) # will print True
print ([] == False) # will print False