Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix inconsistent return statement in python?

I am new to python and i have this project I am working on a small project with two functions where the first returns the index of the first time a difference is spotted in a string. The next function does that but in a list of strings. Now, due to my being an amateur, i have used an excessive amount of if and else statements which resulted in too many return statements especially in the second function, and i get the error [R1710: inconsistent-return-statements]. How do i fix it and can anybody give me clear examples to better pieces of code? Sorry for the question being so long.

IDENTICAL = -1
def singleline_diff(line1, line2):
    """
    Inputs:
        line1 - first single line string
        line2 - second single line string
    Output:
        Returns the index where the first difference between
        line1 and line2 occurs.

        Returns IDENTICAL if the two lines are the same.
    """
    len1 = len(line1)
    len2 = len(line2)
    minimum_length = min(len1, len2)

    if len1 != len2:
        if minimum_length == 0:
            return 0
        for idx in range(minimum_length):
            if line1[idx] == line2[idx]:
                pass
            else:
                return idx
        return idx + 1

    for idx in range(len1):
        if line1[idx] == line2[idx]:
            pass
        else:
            return idx
    return IDENTICAL

def multiline_diff(lines1, lines2):
    """
    Inputs:
      lines1 - list of single line strings
      lines2 - list of single line strings
    Output:
      Returns a tuple containing the line number (starting from 0) and
      the index in that line where the first difference between lines1
      and lines2 occurs.

      Returns (IDENTICAL, IDENTICAL) if the two lists are the same.
    """
    line_no = singleline_diff(lines1, lines2)

    len_lines1, len_lines2 = len(lines1), len(lines2)

    if len_lines1 == len_lines2:

        if (len_lines1 or len_lines2) == 0:
            if len_lines1 == len_lines2:
                return (IDENTICAL, IDENTICAL)
            else:
                idx = singleline_diff(lines1[line_no], lines2[line_no])
                return (line_no, idx)

        else:
            idx = singleline_diff(lines1[line_no], lines2[line_no])

            if line_no == IDENTICAL:
                return (IDENTICAL, IDENTICAL)
            elif line_no != IDENTICAL:
                return (line_no, idx)

    else:
        return (line_no, 0)
like image 287
Mohamed Motaz Avatar asked Feb 20 '19 11:02

Mohamed Motaz


2 Answers

Look at the code here:

if len_lines1 == len_lines2:
    return (IDENTICAL, IDENTICAL)
else:
    idx = singleline_diff(lines1[line_no], lines2[line_no])
    return (line_no, idx)

You could have written the above thing like:

if len_lines1 == len_lines2:
    return (IDENTICAL, IDENTICAL)
idx = singleline_diff(lines1[line_no], lines2[line_no])
return (line_no, idx)

You just don't need an else block to return this expression as this part of code will automatically be called if the control doesn't go into if block. Hope it helps.

like image 174
Abhishek Arya Avatar answered Oct 16 '22 20:10

Abhishek Arya


Where was a semantic mistake in OP's code is in Abhishek Arya's answer

TL;DR - early return:

def your_function():
    if not should_do():
        return # NO RETURN VALUE!
    # rest of the function

...yes, this will no longer emit the inconsistent-return-statements ;)

This Q/A pops also when you search for inconsistent-return-statements, I want to give a brief "common problems" guide for those.

Case A: return value is irrelevant, you just want to exit function early

There are cases, where there are functions (or "procedures" if you want to get technical about it) that just do something, but are not expected to have any return values AT ALL,
at the same time, there may be e.g. some sort of check at the start of the function whether this function run even makes sense, what may first come to your mind, is wrapping the whole function code in an if statement:

def your_function(article):
    if display_content():
        content = get_content(article)
        # do some extensive logic to generate final content
        # ...
        print(content)

...this is oversimplified, but let's hope you can imagine how such coding can pretty quickly fall into a "spaghetti code" if there are more checks and more code in general + it also steals that one "tab" of a space that you so desperately need to fit into your project's max line length.

Luckily, same as in many other programming languages, there IS a way of an early ending of a function by returning at ANY place within the function run, meaning in any "Control Flow" - including if/elif/else, for/while loops, ...

Now you'd probably jump quick to just return None, False, etc. although it would work, you'd still get the pylint inconsistent-return-statements warning - to understand why let's see the warning's message:

Either all return statements in a function should return an expression, or none of them should. pylint(inconsistent-return-statements)

From pylint's point of view, if you put anything after the return it will be considered as an expression. So what to do? Actually, in Python, you CAN return "nothing" (again this is not unique to Python)

def your_function(article):
    if display_content():
        return

    content = get_content(article)
    # do some extensive logic to generate final content
    # ...
    print(content)

Although in Python returning "nothing" should be (and technically, to my knowledge, it is) an equivalent of return None, by physically writing "None" you are expressing the intention no matter the implicity of it.
Don't confuse this though with pylint(assignment-from-none) (Assigning result of a function call, where the function returns None) - where both "return" AND "return None" are considered as returning None!

Case B: Your function has a case when it doesn't return

Quite common mistake especially in a larger code is to create a code part which results in simply not returning anything. This is not exactly OP's case, since they used just a negation of the same condition, but pylint doesn't know that, so here's its thought process:

if SOME_CONDITION: # ok, here's just another condition
    return someReturnExpression # and ok, it returns SOMETHING, let's note that
elif OPPOSITE_OF_SOME_CONDITION: # ok, here's just another condition
    return someReturnExpression # and ok, it returns SOMETHING, let's note that
# WAIT ! What?! THERE WAS NO "else:"! Hmmm...
# ...what happens if both conditions fail? NOTHING WOULD BE RETURNED!
# We need to make a warning about that!
# (fact that sometimes they return SOMETHING and sometimes NOTHING)

So this inconsistent-return-statements could be resolved with

if SOME_CONDITION: # ok, here's some condition
    return someReturnExpression # and ok, it returns SOMETHING, let's note that
else: # ok, here's else
    return someReturnExpression # and ok, it returns SOMETHING, let's note that
# Ok, so if returns SOMETHING, else returns SOMETHING,
# so SOMETHING is returned every time! that's good!

...this in itself works, but it will generate yet another pylint issue

Unnecessary "else" after "return" pylint(no-else-return)

See python actually encourages early returns since it often leads to a cleaner code.
return during function run ENDS(/exits) the function and pylint sees that - it sees that if the condition was true, the function code would simply end there - so what it, Abhishek Arya, me and many others suggest is simply continuing with the code after the if part:

if SOME_CONDITION:
    return someReturnExpression

# ... some more code ...
# ... some more code ...
return someReturnExpression

Case C: Combination

Simply don't combine "just" return with return SOMETHING,
if you really need to return None, simply explicitly return None in that case

def get_article(id):
    article = find_article(id)
    if article.id == 0:
        return None

    return article

This is just an example, this is not how you'd really check for some articles ;)

like image 27
jave.web Avatar answered Oct 16 '22 19:10

jave.web