Weird behaviour of `not` operator with python list - python

When I'm trying to check whether a list is empty or not using python's not operator it is behaving in a weird manner.
I tried using the not operator with a list to check whether it is empty or not.
>>> a = []
>>> not (a)
True
>>> not (a) == True
True
>>> not (a) == False
True
>>> True == False
False
The expected output for not (a) == False should be False.

== has higher precedence than not. not (a) == False is parsed as not (a == False).

This is working as expected. Parenthesis added below to clarify how this is being executed:
not (a == True)
# True
not (a == False)
# True
An empty list, a = [], evaluates to False in boolean expressions, but it does not equal False or True. Your expressions in the middle are testing whether it is equal to False or True, so they both evaluate to False, and not False is True.
You can add parenthesis like below to get what you expect:
(not a) == True
# True
(not a) == False
# False

Related

Understanding precedence of `not` operator [duplicate]

This question already has answers here:
Priority of the logical operators (order of operations) for NOT, AND, OR in Python
(8 answers)
Closed 2 years ago.
I tried to test empty string in Python (empty string should be "Falsy" as they write in: How to check if the string is empty?). However I used a little bit different syntax and get weird result in the following comparison:
not(''); # result: True
not('hello'); # result: False
not('hello') == False; # result: True
not('hello') == True; # result: True - how is this result possible? (False == True: result must be False)
Thank you for the answer!
The precedence here is not ('hello' == False). 'hello' equals neither True nor False, so both 'hello' == True and 'hello' == False are False, which is then negated by not.
>>> 'hello' == False
False
>>> 'hello' == True
False
>>> not ('hello' == True)
True
Truthiness isn't the same as being equal to True. A string can be truthy (i.e. you can decide whether it's more of a "yes" or a "no"), but at the same time not be equal to a boolean value (because a string is a string and a boolean is a boolean).
It's important to understand that not is an operator, not a function. The parenthesis do nothing for the expression, here's how it is read:
not('hello') == True
# is the same as
not 'hello' == True
# which is the same as
not ('hello' == True)
# which is equivalent to
not False
# which is
True
Which happens to evaluate to the same as the expression above (for the same reason that 'hello' == False is False.
The correct way of enforcing precedence with not would be to do
(not something) == True

Why does [] == False evaluate to False but 0 == False to True in python? [duplicate]

This question already has answers here:
Empty list boolean value
(3 answers)
Closed 4 years ago.
I am relatively new to Python and don't understand the following behavior:
Why does the statement
[] == False
evaluate to false, eventhough an empty list is falsy?
Here are more examples - in many other cases it seems that the empty list does behave in a falsy way, just not in [] == False...
>>> 0 == False # what I'd expect
True
>>> not [] # what I'd expect
True
>>> bool([]) # what I'd expect
False
>>> [] == True # what I'd expect
False
>>> [] == False # unexpected
False
>>> bool([]) == False # why does it evaluate to True again now?
True
>>> ([]) == (bool([])) # unexpected
False
>>> (not []) == (not bool([]) # apparently adding 'not' makes it behave as expected again - why?
True
Can somebody please explain this to me? How are these statements internally evaluted? I have a feeling it might be related to chaining comparisons (see e.g. here), but cannot really understand if that's correct and why.
Because falsy isn't False. Falsy just means
bool(some_object) is False
So,
>>> bool([]) is False
True
>>> bool({}) is False
True
>>> bool(0) is False
True

How to test if a value is falsy in Python 3

In Javascript, there is == operator to test if a value is falsy:
'' == false // true
In Python, == corresponds to === in Javascript, which is an exact equation (value & type).
So how to find out if a value is Falsy in Python?
You can obtain the truthiness of a value, by using the bool(..) function:
>>> bool('')
False
>>> bool('foo')
True
>>> bool(1)
True
>>> bool(None)
False
In an if statement, the truthiness is calculated implicitly. You can use the not keyword, to invert the truthiness. For example:
>>> not ''
True
>>> not 'foo'
False
>>> not 1
False
>>> not None
True
To get implicit conversion you can just use not - or (for "truthy") just use the variable in place:
if not None:
print('None')
if not False:
print('False')
if not '':
print('empty string')
if not 0:
print('zero')
if not {}:
print('empty/zero length container')
if 'hello':
print('non empty string, truthy test')
What worked was using ternary:
True if '' else False # False
More verbose than in Javascript, but works.
Even tho this question is old, but there is a not not (kinda hacky), but this is the faster than bool(..) and probably the fastest that's possible, you can do it by:
print(not not '')
print(not not 0)
print(not not 'bar')
Output:
False
False
True

Empty String Boolean Logic

I just stumbled across this and I couldn't find a sufficient answer:
x = ""
Why then is:
x == True
False
x == False
False
x != True
True
x != False
True
Am I supposed to conclude that x is neither True nor False?
to check if x is True of False:
bool("")
> False
bool("x")
> True
for details on the semantics of is and == see this question
Am I supposed to conclude that x is neither True nor False?
That's right. x is neither True nor False, it is "". The differences start with the type:
>>> print(type(""), type("x"), type(True), type(False))
builtins.str, builtins.str, builtins.bool, builtins.bool
Python is a highly object oriented language. Hence, strings are objects. The nice thing with python is that they can have a boolean representation for if x: print("yes"), e. g.. For strings this representation is len(x)!=0.
In a Boolean context, null / empty strings are false (Falsy). If you use
testString = ""
if not testString:
print("NULL String")
else:
print(testString)
As snakecharmerb said, if you pass the string to the bool() function it will return True or False based
>>> testString = ""
>>> bool(testString)
False
>>> testString = "Not an empty string"
>>> bool(testString)
True
See this doc on Truth Value Testing to learn more about this:
Python 2:
https://docs.python.org/2/library/stdtypes.html#truth-value-testing
Python 3:
https://docs.python.org/3/library/stdtypes.html#truth-value-testing
In python '==' tests for equality. The empty string is not equal to True, so the result of your comparison is False.
You can determine the 'truthiness' of the empty string by passing it to the bool function:
>>> x = ''
>>> bool(x)
False

Is it safe to replace '==' with 'is' to compare Boolean-values

I did several Boolean Comparisons:
>>> (True or False) is True
True
>>> (True or False) == True
True
It sounds like == and is are interchangeable for Boolean-values.
Sometimes it's more clear to use is
I want to know that:
Are True and False pre-allocated in python?
Is bool(var) always return the same True(or False) with the pre-allocated True(or False)?
Is it safe to replace == with is to compare Boolean-values?
It's not about Best-Practice.
I just want to know the Truth.
You probably shouldn't ever need to compare booleans. If you are doing something like:
if some_bool == True:
...
...just change it to:
if some_bool:
...
No is or == needed.
As commenters have pointed out, there are valid reasons to compare booleans. If both booleans are unknown and you want to know if one is equal to the other, you should use == or != rather than is or is not (the reason is explained below). Note that this is logically equivalent to xnor and xor respectively, which don't exist as logical operators in Python.
Internally, there should only ever be two boolean literal objects (see also the C API), and bool(x) is True should be True if bool(x) == True for any Python program. Two caveats:
This does not mean that x is True if x == True, however (eg. x = 1).
This is true for the usual implementation of Python (CPython) but might not be true in other implementations. Hence == is a more reliable comparison.
Watch out for what else you may be comparing.
>>> 1 == True
True
>>> 1 is True
False
True and False will have stable object ids for their lifetime in your python instance.
>>> id(True)
4296106928
>>> id(True)
4296106928
is compares the id of an object
EDIT: adding or
Since OP is using or in question it may be worth pointing this out.
or that evaluates True: returns the first 'True' object.
>>> 1 or True
1
>>> 'a' or True
'a'
>>> True or 1
True
or that evaluates False: returns the last 'False' object
>>> False or ''
''
>>> '' or False
False
and that evaluates to True: returns the last 'True' object
>>> True and 1
1
>>> 1 and True
True
and that evaluates to False: returns the first 'False' object
>>> '' and False
''
>>> False and ''
False
This is an important python idiom and it allows concise and compact code for dealing with boolean logic over regular python objects.
>>> bool([])
False
>>> bool([0])
True
>>> bool({})
False
>>> bool({False: False})
True
>>> bool(0)
False
>>> bool(-1)
True
>>> bool('False')
True
>>> bool('')
False
Basically 'empty' objects are False, 'non empty' are True.
Combining this with #detly's and the other answers should provide some insight into how to use if and bools in python.
Yes. There are guaranteed to be exactly two bools, True and False:
Class bool cannot be subclassed
further. Its only instances are False
and True.
That means if you know both operands are bool, == and is are equivalent. However, as detly notes, there's usually no reason to use either in this case.
It seems that all answers deal with True and False as defined after an interpreter startup. Before booleans became part of Python they were often defined as part of a program. Even now (Python 2.6.6) they are only names that can be pointed to different objects:
>>> True = 1
>>> (2 > 1)
True
>>> (2 > 1) == True
True
>>> (2 > 1) is True
False
If you have to deal with older software, be aware of that.
The == operator tests for equality The is keyword tests for object identity. Whether we are talking about the same object. Note, that more variables may refer to the same object.
== and is are both comparison operators, which would return a boolean value - True or False. True has a numeric value of 1 and False has a numeric value of 0.
The operator == compare the values of two objects and objects compared are most often are the same types (int vs int, float vs float), If you compare objects of different types, then they are unequal. The operator is tests for object identity, 'x is y' is true if both x and y have the same id. That is, they are same objects.
So, when you are comparing if you comparing the return values of same type, use == and if you are comparing if two objects are same (be it boolean or anything else), you can use is.
42 is 42 is True and is same as 42 == 42.
Another reason to compare values using == is that both None and False are “falsy” values. And sometimes it’s useful to use None to mark a value as “not defined” or “no value” while considering True and False values to work with:
def some_function(val = None):
"""This function does an awesome thing."""
if val is None:
# Values was not defined.
elif val == False:
# User passed boolean value.
elif val == True:
# User passed boolean value.
else:
# Quack quack.
Somewhat related question: Python != operation vs “is not”.

Categories

Resources