Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling PyLint Warning of Inconsistent Return Statement

Tags:

python

pylint

I'm running PyLint on some code and I'm getting the warning of "Either all return statements in a function should return an expression or none of them should. (inconsistent-return-statements)."

Here is the code I have:

def determine_operand_count(opcode_form, opcode_byte):
  if opcode_form == OP_FORM.VARIABLE:
    if opcode_byte & 0b00100000 = 0b00100000:
      return OP_COUNT.VAR

    return OP_COUNT.OP2

  if opcode_form == OP_FORM.SHORT:
    if opcode_byte & 0b00110000 == 0b00110000:
      return OP_COUNT.OP0

    return OP_COUNT.OP1

  if opcode_form == OP_FORM.LONG:
    return OP_COUNT.OP2

Here "OP_FORM" and "OP_COUNT" are Enums defined earlier in the code.

To me, that code is very readable code and I guess I'm curious what the warning from PyLint is complaining about. In every condition that I have, an "OP_COUNT" type is returned. In fact, if any of these conditionals weren't returning an OP_COUNT, my code would be failing entirely.

This seems to be a warning about my "return statements", suggesting that some aren't returning any sort of expression. But that's clearly not true (so far as I can see) as each return statement is returning something. So I'm guessing this has to do with implied returns?

But to that point, in my original code I actually held "else" clauses for my internal if statements. But when I did that, PyLint gave me another warning: "Unnecessary 'else' after 'return' (no-else-return)."

I did see the following: "How to fix inconsistent return statement in python?", but that didn't seem to reflect the situation in my code.

So it's unclear to me how to satisfy PyLint in this case since the code clearly works and seems to be doing what the warning suggests I need to be doing. Given that, I suspect I'm missing something obvious but that I currently lack the intuition for spotting. Any help to get me spotting what I'm missing would be appreciated.

like image 220
Jeff Nyman Avatar asked Jan 16 '20 11:01

Jeff Nyman


2 Answers

In your case, it might happen for 2 reasons:

1) Your variable name case is for some reason inconsistent: opcode_Form (with uppercase "F") in first if statement (probably you just have mistyped it, since you also have = instead of == at the very same place) and opcode_form (with a lowercase "f") in all other places.

2) More likely, since opcode_form is not type-hinted as being an OP_FORM enum instance, it actually can be of any value, and the final else (for the case when opcode_form is neither OP_FORM.VARIABLE nor OP_FORM.SHORT or OP_FORM.LONG) is missing. So, for example, if opcode_form is some string "string", the function will actually return nothing.

like image 24
trolley813 Avatar answered Sep 23 '22 14:09

trolley813


Pylint complains about what is happening when you reach the very end of the function. What should happen at the end of the function? (added a return and the warning goes away)

def determine_operand_count(opcode_form, opcode_byte):
    if opcode_form == OP_FORM.VARIABLE:
        if opcode_byte & 0b00100000 == 0b00100000:
            return OP_COUNT.VAR
        return OP_COUNT.OP2

    if opcode_form == OP_FORM.SHORT:
        if opcode_byte & 0b00110000 == 0b00110000:
            return OP_COUNT.OP0
        return OP_COUNT.OP1

    if opcode_form == OP_FORM.LONG:
        return OP_COUNT.OP2

    return OP_COUNT.UNKNOWN

This code should work, but in my experience is kind of fragile over time because of the indentation. An alternative is to write it as:

def determine_operand_count_v2(opcode_form, opcode_byte):
    def variable_form(opcode_byte):
        if opcode_byte & 0b00100000 == 0b00100000:
            return OP_COUNT.VAR
        return OP_COUNT.OP2

    def short_form(opcode_byte):
        if opcode_byte & 0b00110000 == 0b00110000:
            return OP_COUNT.OP0
        return OP_COUNT.OP1

    def long_form(_):
        return OP_COUNT.OP2

    opfcn = {OP_FORM.VARIABLE: variable_form,
             OP_FORM.SHORT: short_form,
             OP_FORM.LONG: long_form}

    return opfcn[opcode_form](opcode_byte)
like image 108
FredrikHedman Avatar answered Sep 21 '22 14:09

FredrikHedman