Can anybody please tell me here what is the exact difference between if and if not here in the code.
def postordertraversse(self,top):
m=[]
if(top):
if not self.postordertraversse(top.left):
m.append(top.root)
top_most=m.pop(0)
conv=createlist();
conv.postordertraversse(conv.top)
What i can understand is if top means if top object instance exists then move inside the block and check if not i.e till top.left is not null keep appending.
if x: means "if x is truthy".
if not x: means "if x is falsey".
Whether something is truthy or falsey depends on what kind of object it is.
For numbers, 0 is falsey, and all other values are truthy.
For boolean values, True is truthy and False is falsey (obviously!)
For collections (lists, tuples, dictionaries, strings, etc), empty ones are falsey and non-empty ones are truthy.
So in your example code, the two if statements are saying:
if top is truthy:
if the result of self.postordertraversse(top.left) is falsey:
not in python is like negation in other programming languages.
'not' statement just converts further expression. For example:
not True - False
not False - True
Related
I'm learning Python and I just started learning conditionals with booleans
I am very confused though as to the specific topic of "If Not". Could someone please explain to me the difference between :
x = False
if not x:
print("hello")
if x == False:
print("hello")
When testing this code on a Python compiler, I receive "hello" twice. I can assume this means that they both mean the same thing to the computer.
Could someone please explain to me why one would use one method over the other method?
It depends™. Python doesn't know what any of its operators should do. It calls magic methods on objects and lets them decide. We can see this with a simple test
class Foo:
"""Demonstrates the difference between a boolean and equality test
by overriding the operations that implement them."""
def __bool__(self):
print("bool")
return True
def __eq__(self, other):
print("eq", repr(other))
return True
x = Foo()
print("This is a boolean operation without an additional parameter")
if not x:
print("one")
print("This is an equality operation with a parameter")
if x == False:
print("two")
Produces
This is a boolean operation without an additional parameter
bool
This is an equality operation with a parameter
eq False
two
In the first case, python did a boolean test by calling __bool__, and in the second, an equality test by calling __eq__. What this means depends on the class. Its usually obvious but things like pandas may decide to get tricky.
Usually not x is faster than x == False because the __eq__ operator will typically do a second boolean comparison before it knows for sure. In your case, when x = False you are dealing with a builtin class written in C and its two operations will be similar. But still, the x == False comparison needs to do a type check against the other side, so it will be a bit slower.
There are already several good answers here, but none discuss the general concept of "truthy" and "falsy" expressions in Python.
In Python, truthy expressions are expression that return True when converted to bool, and falsy expressions are expressions that return False when converted to bool. (Ref: Trey Hunner's regular expression tutorial; I'm not affiliated with Hunner, I just love his tutorials.)
Truthy stuff:
What's important here is that 0, 0.0, [], None and False are all falsy.
When used in an if statement, they will fail the test, and they will pass the test in an if not statement.
Falsy stuff:
Non-zero numbers, non-empty lists, many objects (but read #tdelaney's answer for more details here), and True are all truthy, so they pass if and fail if not tests.
Equality tests
When you use equality tests, you're not asking about the truthiness of an expression, you're asking whether it is equal to the other thing you provide, which is much more restrictive than general truthiness or falsiness.
EDIT: Additional references
Here are more references on "Truthy" and "Falsy" values in Python:
Truth value testing in the Python manual
The exhaustive list of Falsy values
Truthy and Falsy tutorial from freeCodeCamp
In one case you are checking for equality with the value "False", on the other you are performing a boolean test on a variable. In Python, several variables pass the "if not x" test but only x = False passes "if x == False".
See example code:
x = [] # an empty list
if not x: print("Here!")
# x passes this test
if x == False: print("There!")
# x doesn't pass this test
Try it with x = None: not x would be True then and x == False would be False. Unlike with x = False when both of these are True. not statement also accounts for an empty value.
In Python, the built-in functions all and any return True and False respectively for empty iterables. I realise that if it were the other way around, this question could still be asked. But I'd like to know why that specific behaviour was chosen. Was it arbitrary, ie. could it just as easily have been the other way, or is there an underlying reason?
(The reason I ask is simply because I never remember which is which, and if I knew the rationale behind it then I might. Also, curiosity.)
How about some analogies...
You have a sock drawer, but it is currently empty. Does it contain any black sock? No - you don't have any socks at all so you certainly don't have a black one. Clearly any([]) must return false - if it returned true this would be counter-intuitive.
The case for all([]) is slightly more difficult. See the Wikipedia article on vacuous truth. Another analogy: If there are no people in a room then everyone in that room can speak French.
Mathematically all([]) can be written:
where the set A is empty.
There is considerable debate about whether vacuous statements should be considered true or not, but from a logical viewpoint it makes the most sense:
The main argument that all vacuously true statements are true is as follows: As explained in the article on logical conditionals, the axioms of propositional logic entail that if P is false, then P => Q is true. That is, if we accept those axioms, we must accept that vacuously true statements are indeed true.
Also from the article:
There seems to be no direct reason to pick true; it’s just that things blow up in our face if we don’t.
Defining a "vacuously true" statement to return false in Python would violate the principle of least astonishment.
One property of any is its recursive definition
any([x,y,z,...]) == (x or any([y,z,...]))
That means
x == any([x]) == (x or any([]))
The equality is correct for any x if and only if any([]) is defined to be False. Similar for all.
I believe all([])==True is generally harder to grasp, so here are a collection of examples where I think that behaviour is obviously correct:
A movie is suitable for the hard of hearing if all the dialog in the film is captioned. A movie without dialog is still suitable for the hard of hearing.
A windowless room is dark when all the lights inside are turned off. When there are no lights inside, it is dark.
You can pass through airport security when all your liquids are contained in 100ml bottles. If you have no liquids you can still pass through security.
You can fit a soft bag through a narrow slot if all the items in the bag are narrower than the slot. If the bag is empty, it still fits through the slot.
A task is ready to start when all its prerequisites have been met. If a task has no prerequisites, it's ready to start.
I think of them as being implemented this way
def all(seq):
for item in seq:
if not item:
return False
return True
def any(seq):
for item in seq:
if item:
return True
return False
not sure they are implemented that way though
Perl 6 also takes the position that all() and any() on empty lists should serve as sane base-cases for their respective reduction operators, and therefore all() is true and any() is false.
That is to say, all(a, b, c) is equivalent to [&] a, b, c, which is equivalent to a & b & c (reduction on the "junctive and" operator, but you can ignore junctions and consider it a logical and for this post), and any(a, b, c) is equivalent to [|] a, b, c, which is equivalent to a | b | c (reduction on the "junctive or" operator -- again, you can pretend it's the same as logical or without missing anything).
Any operator which can have reduction applied to it needs to have a defined behavior when reducing 0 terms, and usually this is done by having a natural identity element -- for instance, [+]() (reduction of addition across zero terms) is 0 because 0 is the additive identity; adding zero to any expression leaves it unchanged. [*]() is likewise 1 because 1 is the multiplicative identity. We've already said that all is equivalent to [&] and any is equivalent to [|] -- well, truth is the and-identity, and falsity is the or-identity -- x and True is x, and x or False is x. This makes it inevitable that all() should be true and any() should be false.
To put it in an entirely different (but practical) perspective, any is a latch that starts off false and becomes true whenever it sees something true; all is a latch that starts off true and becomes false whenever it sees something false. Giving them no arguments means giving them no chance to change state, so you're simply asking them what their "default" state is. :)
any and all have the same meaning in python as everywhere else:
any is true if at least one is true
all is not true if at least one is not true
For general interest, here's the blog post in which GvR proposes any/all with a sample implementation like gnibbler's and references quanifiers in ABC.
This is really more of a comment, but code in comments doesn't work very well.
In addition to the other logical bases for why any() and all() work as they do, they have to have opposite "base" cases so that this relationship holds true:
all(x for x in iterable) == not any(not x for x in iterable)
If iterable is zero-length, the above still should hold true. Therefore
all(x for x in []) == not any(not x for x in [])
which is equivalent to
all([]) == not any([])
And it would be very surprising if any([]) were the one that is true.
The official reason is unclear, but from the docs (confirming #John La Rooy's post):
all(iterable)
Return True if all elements of the iterable are true (or if the iterable is empty).
Equivalent to:
def all(iterable):
for element in iterable:
if not element:
return False
return True
any(iterable)
Return True if any element of the iterable is true. If the iterable is empty, return False. Equivalent to:
def any(iterable):
for element in iterable:
if element:
return True
return False
See also the CPython-implementation and comments.
This question already has answers here:
and / or operators return value [duplicate]
(4 answers)
Closed 4 years ago.
I am trying to return a boolean in a function like this:
return mylist and any(condition(x) for x in mylist)
The behavior should be to return True if the list is empty or if any element in it meets the condition. I am using the first operand as a shortcircuit since any would return True if the list was empty, which is not what I am after.
I would expect [] and boolval to return False since the list is empty, but to my surprise it returns [] whether boolval is True or False. I would expect the first operand to be automatically evaluated as a boolean since it is involved in a comparison operation, and not whatever is happening.
I am not really asking how to solve my problem, which is easily done by an explicit type conversion: bool(mylist), but rather asking what is happening and why.
edit: when I ask "why" this is happening I am not looking for the "facts" only, as they are already explained in the linked duplicate question, but also the reasons behind the implementation of this behavior.
The and and or operators do not return True/False. They return the last thing evaluated (that's the case in other dynamic languages too, eg. javascript).
The official documentation describes that
for and, the first falsy value, or the last operand
for or, the first truthy value, or the last operand
That's by design, so you can create expressions like return username or 'guest'. So, if you want guarantee that a boolean value is returned, you have to
return bool(x or y)
instead of
return x or y
Because as khelwood said:
x and y gives x if x is falsey, otherwise it gives y.
That's the point, (and is not or :-)), so still best is:
return all([my_list,any(condition(x) for x in my_list)])
This has to do with how python evaluate the expression.
An empty list is considered as false by python, that means that the code after 'and' will not be executed, as this will not change the result.
Python does not need to convert the empty list into bool as it is not compared to anything, and just return it as empty list.
This shouldn't change anything for you, if you test the returned value of the function, it will be evaluate the same way as if the function did return False.
pd.DataFrame.all and pd.DataFrame.any convert to bool all values and than assert all identities with the keyword True. This is ok as long as we are fine with the fact that non-empty lists and strings evaluate to True. However let assume that this is not the case.
>>> pd.DataFrame([True, 'a']).all().item()
True # Wrong
A workaround is to assert equality with True, but a comparison to True does not sound pythonic.
>>> (pd.DataFrame([True, 'a']) == True).all().item()
False # Right
Question: can we assert for identity with True without using == True
First of all, I do not advise this. Please do not use mixed dtypes inside your dataframe columns - that defeats the purpose of dataframes and they are no more useful than lists and no more performant than loops.
Now, addressing your actual question, spolier alert, you can't get over the ==. But you can hide it using the eq function. You may use
df.eq(True).all()
Or,
df.where(df.eq(True), False).all()
Note that
df.where(df.eq(True), False)
0
0 True
1 False
Which you may find useful if you want to convert non-"True" values to False for any other reason.
I would actually use
(pd.DataFrame([True, 'a']) == True).all().item()
This way, you're checking for the value of the object, not just checking the "truthy-ness" of it.
This seems perfectly pythonic to me because you're explicitly checking for the value of the object, not just whether or not it's a truthy value.
>What's wrong with this..
Code-1
def first_last6(nums):
if nums[0]==6 or nums[len(nums)-1] == 6:
return True
else:
return False
Code-2
def first_last6(nums):
return (nums[0]==6 or nums[-1]== 6)
How come both True?
There seem to be two questions inside, so I’ll answer both.
First of all, why are nums[len(nums)-1] and nums[-1] the same? When specifying an index, Python allows you to use negative numbers that are interpreted like this: if i in nums[i] is negative, then the index len(nums)+i is returned. So, basically, [-1] will get the last element, [-2] the second to last etc.
The second question is why the two formats are identical:
if expression:
return True
else
return False
and
return expression
expression in this case is an expression that returns a boolean type, so either True or False. The if statements checks exactly that; if the expression equals to true, it will return true, otherwise (if the expression equals to false) it will return false.
So you can (and should, to make it cleaner) just return the expression itself, as it is already true or false.
In the case expression itself is not a boolean expression, the if statement will still check to what boolean type it would evaluate (for example a non-empty string would be true, or a number other than 0 would be true too). To keep the short syntax, you can then explicitely convert the expression to a boolean value, using bool(expression), as larsmans mentioned in the comments.
nums[-k] is a shorthand for nums[len(nums)-k]. To get the k-th last element you use the notation nums[-k]. Usually it is clear what the notation stands for and the compiler knows how to turn that python code into machine code, which is why certain language contructs are possible and others are not. Other short hands include nums[:k] to get the first k elements, nums[:-k] to get all elements up to the k-th last element etc. Via google, python docs, you will find much more on this. List operations are a great strength of the python.
http://www.diveintopython.net/native_data_types/lists.html
uh, because both are exactly the same and they both evaluate to True.