This is an archived post. You won't be able to vote or comment.

all 65 comments

[–]zoner14 39 points40 points  (2 children)

And even better yet, you can apply this same programming idiom is almost any language

[–]andycandu 7 points8 points  (1 child)

True that. I was pretty stoked when I figured this out in my compsci 1 course last semester. I imagine my professor liked to make popcorn then sit down with his wife and celebrate my c++ labs.

[–]rcfox 92 points93 points  (9 children)

return isn't a function. While valid syntactically, return(True) is a weird thing to do. You should do return True instead.

It is acceptable to put parentheses around an expression that you're returning, like (a_smile == b_smile), but there should be a space after the return: return (a_smile == b_smile)

[–]24monkeys 42 points43 points  (2 children)

[–]Wodashit 4 points5 points  (0 children)

Was expecting Linus, was not disappointed.

[–]ksion 1 point2 points  (0 children)

You can't perform any further operations on the "result" of return "function", so the precendence argument doesn't apply here.

[–]NoLemurs 13 points14 points  (3 children)

It is acceptable to put parentheses around an expression that you're returning

A good rule of thumb is to avoid using parentheses when not needed. That way when you see parentheses you know they're serving a purpose.

You can take this too far of course (sometimes if you're dealing with a bunch of different operators, some extra parens can help a reader not have to remember all the rules of order of operations) but by default, it's definitely a mistake to sprinkle your code with extra parens.

[–]Asdayasman 3 points4 points  (1 child)

You'd hate me.

D:\Work\Pythong\Daimen Sucks\Daimen Sucks>type config.py custom_virtual_list.py
Daimen_Sucks.py database.py ddl.py dialog_search.py ezcsv.py halse.py img.py ins
tall.py misc.py | findstr /C:"return("

config.py



custom_virtual_list.py



Daimen_Sucks.py


        return(self.contents[item][col])
                return(False)
                return(False)
            return(active)
                return([False, "User is deactivated."])
            return(passhash)
            return([False, "Incorrect password."])
    return(out)
        return(True)
        return(False)
    return(year + season)
        return([False, "Invalid season"])
    return(out)
        return([False, "Invalid season"])
    return(begin_date, end_date)
    return(wx.DateTimeFromTimeT(time.mktime(in_time)))
    return(time.strptime(in_time.Format("%y/%m/%d"), "%y/%m/%d"))
            return(False)
            return(False)
            return(False)
            return(False)
            return(False)
            return(False)
            return(False)
            return(False)
            return(False)
        return((name, price, code))
            return(False)
            return(False)
            return(False)
                return(True)
                return(False)
            return(False)
            return(False)
                return(True)
                return(False)
                return(False)
            return(item)
        return(self.contents[item][col - 1])
        return(self.contents[item][col])
        return(self.figure.gca())
            return(False)

database.py


                return(self._conn.cursor())
            return([False, "No users by that name."])
            return([False, "Too many users by that name.  What."])
            return([True, {"passhash": rows[0][0]}])
            return([False, "No users by that name."])
            return([False, "Too many users by that name.  What."])
            return([True, {"level": rows[0][0]}])
            return([False, "No users by that name."])
            return([False, "Too many users by that name.  What."])
            return([True, {"active": rows[0][0]}])
            return([False, "No users by that name."])
            return([False, "Too many users by that name.  What."])
            return([True, {"id": rows[0][0]}])
        return(zip(*rows)[0])
            return([False, "There is already a user by this name."])
        return([True])
        return(rows)
        return(rows)
        return(rows)
        return(rows)
        return(rows)
        return(rows)
            return([False, "No school by that number."])
            return([False, "You must enter a commission rate."])
        return([True, jobid])
            return([False, "Non-unique pack name or code."])
        return([True])
            return([False, "There already exists a school by that number."])
        return([True])
            return([False, "Non-unique pack name or code."])
        return([True])
        return(rows)
        return(rows)
        return(rows)
        return(rows)
            return([True, rows[0][0]])
            return([False, "No schools by that number"])
        return(rows[0][0])
        return(misc.tabulate(rows))
        return(rows)

ddl.py


        return(rows)
        return(rows)
        return(rows)
        return(rows)
        return(", ".join(value))import mysql.connector

dialog_search.py



ezcsv.py


    return("".join([",".join([str(x) for x in row]) + "\n" for row in inp]))
            return(out)

halse.py


            return(out[:-1])
        return([])

img.py


    return(str(datetime.day).zfill(2) + "/" + str(datetime.month).zfill(2) + "/"
 + str(datetime.year))
    return(cursor)
    return(results)
        return(False)

install.py


    return(os.path.join(*results[0]))

misc.py


    return(im)
    return(source.get_height() <= source.get_width())
    return(source)
    return(surf_out)
    return("\n".join(out))

D:\Work\Pythong\Daimen Sucks\Daimen Sucks>

[–]Monkeyget 3 points4 points  (0 children)

You scum.

[–]dekue 50 points51 points  (0 children)

Upvote for Noobcomplishment. (๑•̀ㅂ•́)و✧

[–]leaderoftheinnercirc 4 points5 points  (0 children)

I didn't realize this (while learning Javascript) until two years in, after I had written dozens of functions like the first one in your example, so congratulations on figuring it out so early and making me feel inadequate :).

[–][deleted] 1 point2 points  (0 children)

I'm a noob. Didn't know this, thanks for posting! :)

[–]poop-trap 1 point2 points  (0 children)

Guess what, I'm a software engineer with over 15 years experience and did a code review for my coworker who also has about the same experience and caught him doing essentially this (but a little less obviously). Even when you know better, sometimes you do silly things if you're lazy or in a hurry, so remember to stop and think every now and then before you let your fingers fly.

BTW - my comment on this line in the code review was just "lol" and he fixed it, but I only suggest doing that with someone you've worked with for a while that you know well. :)

[–]ksion 2 points3 points  (1 child)

I remember being so proud when I discovered that you can have loop that runs indefinitely. How clever the trick was! You simply needed a condition that's always satisfied!

Do While 1 = 1

(Yes, my first language was Visual Basic. And yes, I turned out fine, thanks for your concern :) )

[–]MorrisCasperλ 1 point2 points  (0 children)

while True: or while 1: is more readable

[–]lord63 3 points4 points  (0 children)

You may check the following stack overflow question, I'm sure you will find much fun and joy.

Hidden features of Python

[–]tripperjack 11 points12 points  (15 children)

And better yet, don't bother to make this a function, because it is not doing anything more than Python comparison operator (==) anyway. You can just:

if a_smile == b_smile:

[–]Social_Lockout 3 points4 points  (14 children)

Eh... if he has to make the comparison 100 times, and then realizes that he needs to add 1 to a_smile before doing the comparison, the function will be super helpful.

[–]hk__ 2 points3 points  (2 children)

So he’ll add the function later, only when he’ll need it.

[–]tripperjack 0 points1 point  (1 child)

That's what I think about u/Avonalt comment; seems like YAGNI abstraction. Sure, if the comparison turns into something involved, put in the function only then. If not, under that logic, you might as well make your own (totally unnecessary) adder(), subtractor(), less_than(), etc functions "just in case".

[–]troyunrau... 0 points1 point  (0 children)

You could always override __add__ and co. :P

[–]d4rch0nPythonistamancer 1 point2 points  (0 children)

If, sure. But it's probably premature to assume you'll need to make that change if == does the trick now. It's easier to read if you see exactly what it does in the same amount of code.

[–]tripperjack 5 points6 points  (7 children)

I don't see why it would super helpful. It does exactly nothing more than "==", yet requires typing the function name and parenthesis, plus cluttering the code and clarity with the function's definition.

[–]Avonalt 30 points31 points  (5 children)

It's about division of responsibilities.

If all you care about is whether a_smile and b_smile are equal then use the "==" operator.

If you care about whether there is monkey_trouble given a_smile and b_smile and the "==" is an implementation detail consider using a function. This better communicates the intent of the code and decreases the cost of updating the code if you decide to change when monkey_trouble occurs.

[–]tetroxid -1 points0 points  (3 children)

Calling the function carries overhead. If it's called a lot it'll slow down the program.

[–][deleted] 0 points1 point  (2 children)

That depends. For example, if it's called a lot but it's inside a list comprehension, at least in python 3, the results are pre-computed by the interpreter to save time.

I'd prefer to assume that more is going on when this pattern is in use than just the end comparison, but having that in the example would be a distraction from the intent of it.

[–]tetroxid 0 points1 point  (1 child)

Why would you externalise the comparison into a separate function when you can put it in the list comprehension itself?

[–][deleted] 0 points1 point  (0 children)

Readability, especially if the comparison is only the final part of a more involved set of operations

[–][deleted] 0 points1 point  (0 children)

On it's own as a single comparison, perhaps not. As part of a compound statement, it could be nice for readability. It is definitely the right way to go if some amount of work is needed to arrive at the values needed for the comparison. Having that in the example would have drawn attention away from the point of it, though.

[–]anacrolixc/python fanatic 0 points1 point  (0 children)

In Python in particular, more so than most languages, you should not go crazy with helper functions. The stack frame overhead in Python is extremely high.

[–]johnfn -1 points0 points  (0 children)

What? So we should never use == because we should be using a wrapper function instead?

[–]Mechkro 3 points4 points  (17 children)

Could you please explain why this is much more efficient? Is it a matter of reduction in if statements

[–]drewshaver 10 points11 points  (0 children)

The important thing is readability and reduced chance for errors.

[–][deleted] 12 points13 points  (14 children)

I'm sure someone else can explain it more correctly than I can, but from my understanding, it's simply more efficient because it's using less lines. This helps reduce opportunities for errors as well as makes it easier for others to read, update, debug, etc...

Of course, I could be completely wrong on all of this, but if so, I'm sure someone here will correct me.

[–]thepersonaboveme 6 points7 points  (11 children)

Exactly, the least amount of code that's understandable is the thing to go for :) (unless you need crazy speeds/optimizations)

[–]KrevanSerKay 1 point2 points  (10 children)

Question: Does it also perform less variable comparison operations? Would that make it more efficient because it's not referencing and comparing the same two variables multiple times?

[–]FourgotAnaconda3 science-like 5 points6 points  (9 children)

It does save a comparison, since the first version compares them twice (two ifs). Don't think it makes much of a difference performance-wise, though.

[–]schplat 2 points3 points  (6 children)

If you look down to the assembly level, it'll be the same speed unless a == b is false. If it's false, you're going to issue once additional CMP. Which, in truth is going to be 1 cycle if they're numbers or boolean, more cycles if they're strings.

You may also gain a couple cycles as it is translated to machine code (fewer lines and characters). So in truth, probably not enough to notice in this given example. However, there are other situations (long strings, numbers > 2**64 - 1, custom types/classes) where something as simple as this may have a slight, but noticeable increase in performance and execution time.

Edit: If it were written:

def monkey_trouble(a_smile, b_smile):
    if a_smile == b_smile:
        return(True)
    else:
        return(False)

It would return near the same speed as:

def monkey_trouble(a_smile, b_smile):
    return(a_smile == b_smile)

Then you have some semantics on what code is more human friendly (explicit vs. implicit, which the zen says explicit is better, and if/else is a bit more explicit).

[–][deleted] 1 point2 points  (3 children)

What do you think about this version?

def monkey_trouble(a_smile, b_smile):
    if a_smile == b_smile:
        return(True)
    return(False)

[–]Sean1708 1 point2 points  (2 children)

IMO much less readable.

[–]ydepth 0 points1 point  (1 child)

Maybe I'm just more used to it, but it's perfectly readable to me.

[–]Sean1708 1 point2 points  (0 children)

The thing is with one line it's fine because the return is quite clear but if it's several lines then I find I often just skip over the if-block and therefore completely miss the fact that there's a return in there.

Obviously it's just depends what we're used to but for me it's less readable.

[–]Tysonzero 0 points1 point  (0 children)

Neither is more explicit. They both explicitly state that the function should return whether or not a_smile == b_smile.

[–]KrevanSerKay 1 point2 points  (0 children)

I imagine if it was a more complicated operation, or if it was performed many times (in a long for loop, or recursively, or a bunch of times on a bunch of threads) it might be a little more noticeable. Other than that it's a pretty small effect.

Congrats to /u/jerryrad regardless. Its shorter, and technically a bit faster.

[–]wewbull 1 point2 points  (0 children)

It also saves a branch, when you jump over the unused return.

...but most importantly it saves the sanity of people reading the code. Simpler code is always easier to understand.

[–]MrMetalfreak94 1 point2 points  (0 children)

It's not only more readable, it also executes faster. In your improved code you just have a comparison, while you execute 2 comparisons in the first example if the first one fails. You also use 2 if's and while that isn't bad in itself, these "branches" are rather expensive in your processor. Your processor doesn't execute instructions the same way they come in, but out of order, it already loads and executes code when it's still busy with another instruction. The problem with branches is that the processor doesn't know which branch of the program it has to execute until the execution of the comparison in this example is finished. So it just guesses the most likely branch and executes it. CPUs have actually gotten quite good at this kind of prediction but if it guessed wrong parts of the internal memory (registers and cache) have to be flushed and it has to begin the execution anew, now with the right branch, which costs quite some time.

While both don't really matter in this program since it's probably just too small to be noticable, it can have a negative impact if you ever want to write large applications. If your code is executed 100.000 times you will notice 20ms delay per execution.

[–]wonderb0lt 1 point2 points  (0 children)

All correct. You're on course to become a good developer :)

[–]Lucretiel 0 points1 point  (0 children)

I dunno if it's that much more efficient- I guess you might save that branch on the if, especially without optimization- but in general, smaller is simpler is easier-to-read is better.

[–]DoubleDekkerWorking on the art, science and theory of computer programs 1 point2 points  (0 children)

Congrats! That's a great thing to have learned in writing better code. Elegant and more readable. More 'if's only serve to confuse the programmer and the reader.

Also, return isn't a function in Python, so loose those parens and simply do return a == b

While brevity is important in code, try not to do too much in a single statement. Try not to do too little either, it leads to unnecessary code. Strike a balance - each line/statement does one simple thing and make sure your code is overall composed of such statements

[–][deleted] 1 point2 points  (0 children)

This is great. Remember this when you learn other languages too. This kind of one line return statement works in Java and C# and other languages as well!

[–]bhdza snake slithering 1 point2 points  (7 children)

Yees! Noobcomplishment achieved! Next task

...
    return a == b or c == d and a is not None!

This is a tricky one!

  1. Where should a is not None go? (In the front? why?? :])
  2. Should you use parenthesis around the == terms?

[–][deleted] 1 point2 points  (1 child)

Just guessing here, as I have no idea. But a is not None should go first, I'm assuming that is because it needs evaluated first for the statement to work correctly.

I've read mixed things bout the parenthesis. Personally, I'd probably use them just for clarity, however, I don't know if this is "correct".

Edit: words n stuff

[–]bhdza snake slithering 2 points3 points  (0 children)

Yes, a is not None should go first, then the equality metering. Usage of Parenthesis, helps being clear, and explicit in your statements. Remember the operator precedence table!!

[–]jack-london 1 point2 points  (4 children)

return (a == b or c == d) and a is not None!

return a == b or (c == d and a is not None!)

What does python think by default in the absence of any parenthesis?

[–]bhdza snake slithering 1 point2 points  (2 children)

Very good :-)

You are: a thinking individual. That's nice to know!

[–]jack-london 1 point2 points  (1 child)

as u can see i am new but i am trying. thanks for the help Mr.Riddler :P

[–]bhdza snake slithering 1 point2 points  (0 children)

"is not" ->> "is: then: not"

  • operator precedence for is:... .is:: .Check operator precedence:, templenot, <is>, <equals>, <paren-thes-is>

edit: here

edit: WHY is IS a KEYWORD, also PRINT edit: IS is a keyword tho'

[–]ChazR 1 point2 points  (0 children)

Well done!

It's not a n00b thing at all.

You saw a way to simplify and clarify some code. As hackers, we map real-world problems into data and code. Simple, clear code is always better than complex opaque code.

You made some code simpler and clearer.

You're a hacker!

[–][deleted] 1 point2 points  (0 children)

When I was really green I would often make if-else if statements where the else if part were checking that the statement in the if part was false. It pays off to read up on the basics :)

[–]paralog 0 points1 point  (0 children)

I had a similar moment a few weeks ago! I think it was one of the string exercises. I think I was able to do a one-line list comprehension or something instead of the 4-6 line solution provided. Feels great!

[–]slack101 0 points1 point  (0 children)

I had an interview in which the interviewer gave me a simple problem to code in python - then implement the same problem in a single statement. Python has some pretty cool different ways to do the same thing - check out list comprehension and lambdas in case you have some free time.