1

Simple question that I can't find the answer for.

Take the function:

The below looks nice, i.e. more readable, given the else and the aligned spacing between the two return statement. However the else is completely pointless, and that makes it feel a little dirty.

def get_val(self):
    if long_var < other_long_var and var < other_var:
        return true
    else:
        return false 

Note the two conditions and the long line, this is to express that the following is not applicable in this example:

return true if this else false

However the below is not as readable, but only slightly. It is more elegant as the useless else is omitted.

def get_val(self):
    if x:
        return true
    return false 

Is there a Pythonic bias for either of these styles?

If not, is it purely down to the developer?

EDIT: To be clear, it is an example function. I was trying to express the need for a function that has a condition and returns true of false. This is a purely stylistic question

cardycakes
  • 431
  • 1
  • 4
  • 12
  • 1
    why not use `return x`? – ktzr May 16 '18 at 18:10
  • 4
    @ktzr I hope you mean `return bool(x)`. – miradulo May 16 '18 at 18:10
  • 1
    why do you think this is _not as readable_. Also this is already discussed @ [It is more efficient to use if-return-return or if-else-return? ](https://stackoverflow.com/questions/9191388) – akshat May 16 '18 at 18:11
  • 1
    You can also `return True if x else False` – carrdelling May 16 '18 at 18:12
  • Why does it matter if it's pythonic or not? Efficient and readable (for others) code should be the goal. – Aydin K. May 16 '18 at 18:13
  • 1
    @miradulo If you know `x` is bool, `return x` makes more sense. Or if you know your caller only cares about val's truthiness, not the actual val. Of course in a toy example like this with meaningless names that doesn't do anything but raise a `NameError`, it's hard to guess what the actual use looks like… – abarnert May 16 '18 at 18:15
  • @abarnert Who knows, yeah, just pointing out it doesn't stick to their signature. – miradulo May 16 '18 at 18:19
  • Honestly, the fact that this looks like an unnecessary getter method is a lot more of an issue for whether it's Pythonic or not, and the fact that it appears to be getting a global rather than a member even more so. – abarnert May 16 '18 at 18:21
  • Anyway, there are differences in readability and connotations between the two implementations, but they'll only really show up up in more realistic examples. For example, if `x` is an uncommon condition that needs to be dealt with early (like `if not self.initialized: return None`) while the rest of the function is 8 lines of fancy computation, using an `else` is just indenting your main code path. If the two cases are conceptually similar and their implementations are similar, using an else is a way to make that visible. If you're just reproducing `bool(x)`, neither one is worth doing. – abarnert May 16 '18 at 18:23
  • It could be argued that you should only have one `return`. In a trivial example like this then that would add nothing, but in a larger function there is a case for only having one `return` point at the end of the function. Like many things in programming, there is no hard rule for when this is better, only when it is easier to maintain – cdarke May 16 '18 at 18:31
  • @cdarke It _could_ be argued, but it's generally not a very compelling argument in Python, and primarily made by people trying to write C style in Python, or people who like to micro-optimize by manually inlining as much as possible into one giant function. – abarnert May 16 '18 at 18:42
  • @ktzr it is simply an example, see my edit. – cardycakes May 16 '18 at 21:59
  • @akshat thanks, seems like this is a duplicate – cardycakes May 16 '18 at 22:04

3 Answers3

3

If you're just trying to find if the value of a paramater is either True or False, you can use python's built-in function bool.

x = ""
bool(x)
>>> False

x = "something"
bool(x)
>>> True

Also, you should check the official docs: https://docs.python.org/3.6/library/functions.html

Hope it helped.

dolan
  • 1,716
  • 11
  • 22
Lelor
  • 46
  • 4
2

In such short cases, I would prefer:

def get_val(self):
    return x
  • it is readable for experienced programmers (who know Python)
  • performance faster than anything below, though the difference will be minimal

Secondly, in my view still pythonic (often seen in codewars.com):

def get_val(self):
    return True if x else False

But I guess, the style guides will recommend:

def get_val(self):
    if x:
        return True
    else:
        return False

Your second example might not be very pythonic ...

In codewars.com I have also often seen:

def get_val(x):
    if x == "": return yz
    elif x == "B": return xyz
    else: return z

which might be a kind of switch/case imitation in Python, though I don't think that style guides will support this ...

Gwang-Jin Kim
  • 9,303
  • 17
  • 30
  • Using a chain of `elif` in place of `switch/case` is definitely Pythonic; it's half of [the official design FAQ answer to why Python doesn't have or need `switch/case`](https://docs.python.org/3/faq/design.html#why-isn-t-there-a-switch-or-case-statement-in-python). (The other half is dict of values or functions.) Doing the one-liner thing… PEP 8 strongly discourages it, but for really trivial cases like this, you see it in code even by some core devs. (But if the chain is long enough that saving vertical space matters, a dict is likely to be clearer, and more efficient to boot…) – abarnert May 16 '18 at 18:46
  • Thank you for your comment, abarnert. True, a `dict` will be clearer ;) . And yes, the official recommendations might discourage the one liners. But sometimes, in `codewars.com` I found the short solution very tempting ;) . – Gwang-Jin Kim May 16 '18 at 19:17
0

For the example you've given (which is minimal and complete, as it should be), both options are clear and easy to understand.

The easiest (and most pythonic) way would be:

def get_val(self):
    return bool(x)

Let me comment on a more general case. Quoting from import this:

In the face of ambiguity, refuse the temptation to guess.

While the second option might appear more elegant, it is also ambiguous: Are you returning False because x is False, or because none of the previous return statements have been triggered?

Thinking of a slightly more complex example, I'd suggest to use the final return statement to give you e.g. some default option, a warning, or a ValueError.

def myfunc(x, mode):
    if mode == 'square':
        return x**2
    if mode == 'cube':
        return x**3
    return x
Daniel Lenz
  • 3,334
  • 17
  • 36
  • You might want to justify why you believe it to be ambiguous. – miradulo May 16 '18 at 18:15
  • 1
    Thanks for the feedback, I've included a very simple pythonic option and some thoughts on a more general case. – Daniel Lenz May 16 '18 at 18:29
  • 1
    @DanielLenz thanks for the answer. The Python quote answers the question elegantly I feel - as you put it. Your last example does explain the logic behind my second answer, 'by default return false, unless this is true', but it does also possess some ambiguity as you have stated. – cardycakes May 16 '18 at 21:57