Python will always return None, if no return is specified at the point of exiting the function call. Your options are:
- return something else if the condition is not met.
- ignore the function if it returns
None
option 1 (return something else when the condition isn't met):
def html_check(td, text):
if td.text == text:
value = td.find_next('td').text
return value
return "no value found"
option 2 (ignores the function if None is returned):
if html_check(td, 'section'):
# do things
Answer from Christian W. on Stack OverflowSeveral weeks ago a was pursuing some of the posts here on python and stumbled on an article about bad programming habits. I cant find the article again for reference but right at the top was a heady warning to avoid returning a meaningful None. AT the time I thought, 'well thats just droll and I never do that anyway', but as it turns out I do it all the time. If the function finds the correct thing then return the correct thing otherwise just end the function and python will return None for you.
So do you guys do the same thing? Whats wrong with returning None in the first place? What strategies do you use to avoid returning None?
Might not be exactly on topic but I wish more people would code their functions to NOT return None and instead return expected type.
BeautifulSoup is the biggest perpetrator of this. Whenever you parse the tree/soup you'll either get a list of results or a single result, now if no results are found instead of getting an empty list you get None returned, which in turn requires you to make checks on every single lookup which really messes up your code up and makes everything look ridiculous.
switched to lxml/xpath and never looked back.
Per PEP-20, explicit is better than implicit, so when I'm writing code where None is a valid answer, I explicitly return a None. If it's an error to get to the end, raise an error.
If it's a hack/preliminary code, I don't care. For production level code, I have one return and it's the last line of the function/method. For a short function, I don't really care, but definitely for a long function.
Python will always return None, if no return is specified at the point of exiting the function call. Your options are:
- return something else if the condition is not met.
- ignore the function if it returns
None
option 1 (return something else when the condition isn't met):
def html_check(td, text):
if td.text == text:
value = td.find_next('td').text
return value
return "no value found"
option 2 (ignores the function if None is returned):
if html_check(td, 'section'):
# do things
You can specify a default value, to return, in case no element matches. Something like:
def html_check(td, text):
if td.text == text:
value = td.find_next('td').text
return value
return "Default Value"
Also, you can spcify the default value via argument, which would somewhat look like :
def html_check(td, text, default_value):
if td.text == text:
value = td.find_next('td').text
return value
return default_value
And, then use it like:
for tr in table_body.find_all('tr'):
for td in tr:
description= html_check(td, 'Description', 'Default Description')
category = html_check(td, 'Category','Default Category')
department = html_check(td, 'Department', 'Default Department')
justification = html_check(td, 'Justification', 'Default Justification')
print(description, category, department, justification)
Videos
Python and I are NOT getting along today.
I have the script below, which takes arguments like username and fromdate and passes it into the appropriate place in the URL (the link variable). Now, if the user just inputs username and doesn't input fromdate, Python will return None instead of nothing. Why do you do this, Python!? I never asked you to!
How can I avoid this monstrosity?
Command
main.py -u jacksfilms
Script
import requests, re, argparse
parser = argparse.ArgumentParser()
parser.add_argument('-u','--username', required=False)
parser.add_argument('-from','--fromdate', required=False)
parser.add_argument('-to','--todate', required=False)
args = vars(parser.parse_args())
username = args['username']
fromdate = args['fromdate']
todate = args['todate']
link = "https://web.archive.org/cdx/search/cdx?url=twitter.com/{}/status&matchType=prefix&from={}&to={}".format(username,fromdate,todate)
data = []
c = requests.get(link).text
urls = re.findall(r'https?://[^\s<>"]+[|www\.^\s<>"]+', c)
for i, url in enumerate (urls):
data.append(f"{i}: {url}\n")
print(data)https://youtu.be/EY-oLHxpKrI
There is nothing wrong with returning None.
In most cases, you don't need to explicitly return None. Python will do it for you. This is an altered version of your foobar which behaves identically without explicitly returning None:
def foobar(arg):
if check:
return result
# If not check, then None will be returned
Still, even if Python implicitly returns None, there is a value in being explicit; Your code becomes easier to read and understand. This is a constant trade-off for which there is no general answer.
I think returning None is a "no go" from a usability standpoint rather than style. As briefly mentioned in this answer, consider raising an exception instead. For example:
def foobar(arg):
# connect to page by httplib
# check for arg in a certain pattern by lxml
if not check:
raise ValueError("arg did not match pattern in lxml")
return result
try:
result = foobar(arg)
except ValueError:
result = None
if result is not None:
# do stuff
else:
# do other stuff
The advantage of this approach is that it makes it explicit when there is not a match. Other people using your function won't need to know that None is the return value they should expect when there isn't a match and they can handle the exception as they see fit.
There is no such thing as "returning nothing" in Python. Every function returns some value (unless it raises an exception). If no explicit return statement is used, Python treats it as returning None.
So, you need to think about what is most appropriate for your function. Either you should return None (or some other sentinel value) and add appropriate logic to your calling code to detect this, or you should raise an exception (which the calling code can catch, if it wants to).
To literally return 'nothing' use pass, which basically returns the value None if put in a function(Functions must return a value, so why not 'nothing'). You can do this explicitly and return None yourself though.
So either:
if x>1:
return(x)
else:
pass
or
if x>1:
return(x)
else:
return None
will do the trick.