Search code examples
pythonfunctionspyderconventions

Regarding good coding practices, what is meant by "Useless return at end of function and method"?


I'm using Spyder to create a web scraper, and things are moving smoothly so far. As a rookie, Spyder's Code Analysis function is something I find useful for improving the standard of my code. However, while I usually understand its instructions/recommendations, I've recently run into a bit of a blip. I'll post some sample code first:

def payments(): #### This is line 59 on the editor. Preceding it is another function with a a format similar to this one.
    """Obtains data on the weekly payments in the country"""
    html = get(source["Payments"]).text
    html = bs(html,"lxml")
    location = "/home/oduduwa/Desktop/Python Projects/Financial Analyser/CBN Data/Payments.csv"
    def file_check():
        headings = [i.text for i in html.find_all(width="284")][:10]
        headings.insert(0, "Date")
        if isfile(location) is False:
            with open(location,"w") as file_obj:
                writer(file_obj).writerow(headings)
                return
    file_check()
    file = open(location,"r").read()
    dates = [i.text.strip()[8:] for i in html.find_all("th",colspan="2")]
    values = [i.text.strip()[4:] for i in html.find_all(width="149") if i.text.strip()[4:]!=""]
    values = array(values).reshape(int(len(values)/10),10)
    values = insert(values,0,array(dates).transpose(),axis=1)[::-1]
    for i in range(len(values)):
        if values[i][0] not in file:
            with open(location,"a+",newline=("\n")) as file_obj:
                writer(file_obj).writerow(values[i])
    return

The code runs fin and does everything it should. What I don't really understand, however, is Spyder's statement that there's a useless return call in the code block. Here's what it says specifically: enter image description here

But from what I gather, every function call is necessary in this coding block. What could I have missed? Thanks for your time!


Solution

  • Python functions implicitly return None by default. The following function definitions are equivalent.

    def foo():
        pass
    
    def foo():
        return
    
    def foo():
        return None
    

    In my opinion, it is good practice to either

    1. have no return statement at all - this indicates that you are not supposed to assign a name to the return value when calling the function, or
    2. explicitly return None, to indicate "no result" for a function that could return a meaningful value, or
    3. use just return to make a function that returns no meaningful value stop execution.

    Example for situation 1:

    def switch_first_last_in_place(lst):
        'switch the first and last elements of a list in-place'
        lst[0], lst[-1] = lst[-1], lst[0]
    

    This function implicitly returns None and you are not supposed to issue

    result = switch_first_last_in_place([1, 2, 3])
    

    Example for situation 2:

    def get_user_info_from_database(username):
        'fetches user info, returns None if user does not exist'
        if user_exist(username):
            return query_db(username)
        else:
            return None
    

    This function explicitly returns None to indicate a user was not found. Assignments like

    result = get_user_info_from_database('Bob')
    

    are expected. The part

    else:
        return None
    

    is unnecessary but I like being explicit in cases where None is a meaningful return value.

    Example for situation 3:

    def assert_exists(thing, *containers):
        'raise AssertionError if thing cannot be found in any container'
         for container in containers:
             if thing in container:
                 return
         raise AssertionError
    

    Here, return is merely used to break out of the function.


    I don't like the bare return at the end of the functions in your example. It is not used to end execution and those functions cannot return other values. I would remove it.