Does this Python expression make sense? - python

I found this kind of expression several times in a python program:
if variable is not None:
dothings(variable)
It seems strange to me, and I think that it has no more sense than:
if variable:
dothings(variable)
Maybe I don't know Python enough, and the expression is explained somewhere?

variable could be 0, or False, or [], or (); be 'falsy' in other words, and then the if statement would be skipped.
See Truth testing for more detail on what is considered false in a boolean context.
In short, testing if variable is not None allows variable to be anything else, including values that would otherwise be considered False in a boolean context.

Some values are falsy, but are not None. You may still want to dothings() to those values.
Here are the things that are falsy in Python 2. (You may want to change the '2' in the URL to a '3' to get the values for Python 3, but it didn't change much.)

E.g.
i = 0
if i is not None:
print i # prints i
if i:
print i # prints nothing

In the google voice python implementation I came across this as well, their use was during a function call. The parameters are defaulted to "None" and then when the function is called they can check if the values are changed or the default.
I.E.
def login (user=None, password=None)
if user is None:
user = input('Please enter your username');
...
return <something>;
called by
login()
OR
login(user='cool_dude')
OR
any combination of user/password you wish.
Additionally your "update" of the logic implies that variable == true or false. That is not correct for all cases (it may work in some cases but I'm throwing them out, since it's not a general case). What you are testing by using the "NONE" logic is whether the variable contains anything besides NONE. Similar to what I was saying above, all the "login function" was doing was determining if the user passed anything, not whether the value was valid, true, etc.

Related

The None Value/Code in Automate the Boring Stuff

The text says the following:
In Python there is a value called None, which represents the absence of a value. None is the only value of the NoneType data type. (Other programming languages might call this value null, nil, or undefined.) Just like the Boolean True and False values, None must be typed with a capital N.
This value-without-a-value can be helpful when you need to store some-thing that won’t be confused for a real value in a variable. One place where None is used is as the return value of print(). The print() function displays text on the screen, but it doesn’t need to return anything in the same way len() or input() does. But since all function calls need to evaluate to a return value, print() returns None. To see this in action, enter the following into the interactive shell:
>>> spam = print('Hello!')
Hello!
>>> None == spam
True
Behind the scenes, Python adds return None to the end of any function definition with no return statement. This is similar to how a while or for loop implicitly ends with a continue statement. Also, if you use a return statement without a value (that is, just the return keyword by itself), then None is returned.
I think I understand what None is, but I am not understanding the code. Why is it that spam is then equal to None when it was assigned to be print('Hello!')? When I enter spam into the interactive shell immediately after the assignment it returns nothing. I get a feeling it is because the argument Hello! is immediately forgotten when print() is called and returns a value, but if I have defined spam to be the print() function with the argument Hello! passed through should it not always return Hello!?
To add to the comments and be more clear, your print() function printed 'Hello!' to the screen and returned None to the program. Printing and returning are not the same thing--printing is for the user, returning is for the program. The print goes to the screen only and (usually) cannot be further used by the program. The returned value can be stored in a variable, such as spam, and used further.
The distinction between printing and returning is important enough that the Python standard is that if a function prints something it should not return any value other than None, and if the function returns a value it should not print anything. This standard is not followed by many other languages (most notoriously C) and is not consistently followed in Python, but this distinction does help the clarity of Python. If you want to study this concept further, do a search on "side effects" in programming.
You are assigning spam to the print() function which doesn't return anything, aka None

How to refer to "True-like" and "False-like" when documenting a function?

Strongly related question.
When writing docstrings for my functions in python, I sometimes want to write something like this about argument specifications:
def foo(bar):
"""
Do some stuff.
bar : callable
must return True if XXX and False otherwise.
"""
if bar(...):
... # code goes here
However, this is not perfectly precise, because in this example bar could be returning any object that will be evaluated to True in the if-statement when the conditions XXX is fulfilled. Such a callable would be a perfectly valid argument to pass to foo.
How should I formulate my documentation to reflect that foo does not strictly requires bar's output to be a boolean?
My first move was to write something like "[...] must return an object that will be evaluated to True if ...", but I find it obfuscated.
This is a slang question! I've always wanted to answer one of these!
Ahem.
The term for something that evaluates to True when used in an if statement is "truthy". The term for something that evaluates to False when used in an if statement is "falsy" or "falsey". So, your documentation can be written like this:
def foo(bar):
"""
Do some stuff.
bar : callable
must return a truthy value iff XXX.
"""
if bar(...):
... # code goes here
"Iff" is more slang, this time from the mathematical world. It means "if and only if". These words are commonly used in programming contexts, so I expect most programmers will understand them; if not, truthy, falsy, falsey and iff all come up with their respective correct meanings when searched in a search engine.
I'm not sure if there's a standard for this, but based on python's Truth Value Testing you would probably be safe writing something like
def foo(bar):
"""
Do some stuff.
bar : callable
when tested for truth value, return value should evaluate to True if and only if XXX.
"""
if bar(...):
... # code goes here
I would suggest that is is just fine to say "must return True if XXX and False otherwise." Because of duck typing, I read this the way you intend. Further, this seems to be standard in how the Python standard library documents things.
In fact, if you do strictly require the value to be True or False and use this language, I will have a very bad day tracking down this bug!
As others have said, "truthy" and "falsy" are fine, well-understood alternatives if you are still concerned.

What was the rational to make None a default return value in python instead of checking it as it is done to uninitialized variables

In Python you can declare a function that doesn't explicitly return a value. For example, you can write:
def launch_aborted():
call_KimJongUn()
# oops we forget to return a value
and then successfully use it in an if statement, for example:
if not launch_aborted():
launch_ballistic_missile()
In a similar situation, the use of uninitialized variables, Python recognizes an error and throws an exception. Python doesn't treat uninitialized variables as None by default as it does with function return value.
# if the variable launch_aborted wasn't assigned yet
# interpreter throws NameError or UnboundLocalError here
if not launch_aborted:
# this code will not be exceuted
launch_ballistic_missile()
This behavior masks errors. If a function has a bug in its declaration, if not all its control paths return a value, it will be difficult to find this bug because by default it returns None and None is also a valid value in boolean expressions and assignments.
I am looking for any justification of this design decision other than simplicity of implementation. I understand that it would need additional check in a caller to track this error and it may degrade performance slightly, but this doesn't look like a reasonable argument here, the similar check for a variable state has also introduce a delay.
If you're interested in mitigating this problem for yourself, check out type annotations. They let you specify explicitly whether your functions can return None or not, and type checkers like mypy can then tell you whether your code might break if they do.

Why does get_name_by_addr return '' and org_by_addr return None?

I am currently testing one of my classes which sets variables with the help of pygeoip.
org_by_addr returns None when there is nothing found in the database:
seek_org = self._seek_country(ipnum)
if seek_org == self._databaseSegments:
return None
While the country_name_by_addr function returns an empty string.
This forces me to check if the return is None and then setting it to '' to have the variables uniformly.
Does anybody know, what the reason is to give different returns when there is no entry in the database?
Other than the obvious "variable uniformity", what is the point of changing the NoneType to an empty string? There is a reason why
bool ('') == bool (None) == False
In my opinion this is a stylistic difference. However, when a package has different return types like this, it can hint several things:
-if the function returns None, you can probably guess that the function would return an instanced object if a match was found in the database.
-if instead of returning None, the function returns an empty string, you can at least expect the output of that function to return a valid string when an entry is found in the database.
-if the function returns 0 instead of None, you can probably guess that the function would return a number of some sort if an entry was found in the database
So really it's mostly about informing the user in some way about what a valid return type would be.
My final suggestion would be to do away with the traditional thought of "types" when using Python. By that I mean the C philosophy of typing. In python there is a reason that you can say:
if result:
#some code
And have it be valid across several different "types".

Return True/False - when to use it over just return

I have searched over internet why i should use return False/True over just return but can not find the answer.
Why would i want to have statement return True/False inseatd of just return ?
Can you please show me an example ?
def test(var):
if var > 5:
return True
else:
return False
test(8)
>>> True
#------------------------
def test(var):
if var > 5:
return
else:
return
test(8)
>>> None
Analogy: A function is a cloneable assistant ready to perform a task, and give you an answer. The task is defined by the parameters of the function (the stuff inside the parentheses). Let's rewrite the names to give them semantic meaning (i.e. names which illustrate what we expect).
def isXGreaterThanY(.....
Here, the name of the task is "is X greater than Y?". If you go up to your cloneable assistant and ask "is X greater than Y?", your assistant will not be able to accomplish what you want unless you tell them what X and Y are.
def isXGreaterThanY(x, y):
.........
Now I can start to explain where you may be going wrong. One error at this level of programming is that just because you see something that does almost what one wants on a webpage, one may be tempted to copy it syntactically and try to fiddle around with the syntax and hope it will just work. This will never work. It is not the point of programming.
Some everyday people think that programming is about magic words (not that I am implying you think that) that solve your problem. This is not the case. Rather, programming is (classically) about being able to make automatons (these little assistants) which manipulate information for you. The rote, mechanical manipulation of information is what computers are good at. We want our tasks to be replicable though, so we give them names like "is X greater than Y?", and specify them in what is known, aptly, as procedures (a.k.a. functions).
Let's consider what you wrote:
def isXGreaterThanY(x, y):
if x > y:
return True
else:
return False
A procedure is all about control flow. Each part of the procedure is either a statement or expression (which you can, at this level, consider to be the same thing). A procedure usually has an answer: whenever control flow hits a "return ANSWER" statement, the entire procedure stops (the task is finished) and your magical assistant returns to you with the answer on a piece of paper with ANSWER written on it. A procedure which returns an answer is known as a 'function', and this is almost always what we want (procedures which do ugly 'side-effects' behind the scenes are usually not what we want).
Below, I illustrate the idea that takes us from syntax (what we write down) to mechanical actions. A procedure is made up of syntactic expressions, and each expression may have subexpressions, etc.
We have the if __ then __ else __ statement, which consists of three subexpressions:
the query clause of x > y, which consists of:
the _ > _ operator acting on:
the variable x
the variable y
the "then" clause of return True, which consists of:
the return statement, returning:
the literal boolean value True
the "else" clause of return False, which consists of:
the return statement, returning:
the literal boolean value False
This 'syntax tree' is what the computer sees. Now, the programming language associates meaning to these expressions: it knows how to navigate this tree in what is known as "control flow". In particular, in the programming language Python, we know that when we see an if-then-else statement, that first we check the test condition. In this case we look at the test condition and notice it is a naked comparison (we ask the CPU, and it gives either True or False back). If the comparison is true, we will do the "then" clause, which returns; i.e. hands you a slip of paper with the answer True. If the comparison was false, we'd do the "else" clause, and hand you a slip of paper with the answer False.
In this way, whenever you ask your assistant "is X greater than Y? where X=... and Y=...", your assistant will (in effect) look at the instructions you've specified in the procedure, and interpret them with the assistant's eye being always fixed on one expression at a time (the "control flow" can be thought of as a highlighted or underlined 'active' subexpression, i.e. control flow is the path your assistant's eye takes while looking through the code). In this particular case, your procedure begins with an if-then-else clause, which it interprets as a branching point in the control flow (a fork in the road); it takes the appropriate branch, and in this case, will discover one of the two 'return' statements, and then dutifully give you a slip of paper.
Control flow is determined by the semantics (meaning) behind special control-flow statements, such as if-then-else. Other control flow structures are interpreted differently. for x in range(7): ... will pretend x is 1 and execute ..., pretend x is 2 and execute ..., etc.
A while True: ... will loop forever, performing the ... over and over again.
A break (break out of) means "stop the while loop" or "stop the for loop prematurely".
A continue means "skip the rest of the ... in this while/for loop, but keep on looping".
You can implement your own control flow using the above and your own custom functions, with what is known as recursion (another topic outside this answer's scope).
That is control flow and imperative programming in a nutshell.
By the way, it is better form to do this:
def isXGreaterThanY(x, y):
# this is a comment
# you can insert a print x>y here, or print(x>y) depending on your version of python
return (x > y)
The expression x > y evaluates to True/False before it's fed into the if-then-else statement. So, you could just return the expression as the answer. However, by that point, your function is simple enough that you wouldn't write a function answer:
#print isXGreaterThanY(1,3)
print (1 > 3)
One major problem is that your second function will return None either way. Returning a boolean value is a way to have the return value of your function be meaningful/useful elsewhere.
If it returns a value like True or False, you can in turn use the return value of your function in cases like:
if test(8):
# do something it returns True
else:
# do something otherwise
Otherwise, you function is meaningless because test() will return the same thing regardless of input.
I was once told that a function should either "do something" or "return something". Your second example function, doesn't "do anything", because the > comparison has no effect if you are not making some choice based on the results of that comparison. It also doesn't really return anything (at least not anything meaningful) because it will return None no matter what - in fact, even if you remove the return keyword, it will still just return None.

Categories