views:

173

answers:

9
+4  A: 

The better is the one you like better. I would use first version with if but this is very personal.

Michał Niklas
+1  A: 

Second one is more pythonic, and I normally use that.

S.Mark
does that mean that the `if` construct is not Pythonic? what constitutes "Pythonic" ?
ghostdog74
IMO it's more Pythonic *if* `var` happens to be boolean. Otherwise, probably not, though the context may change my mind.
Steve314
+2  A: 

the first version is more intuitive to me. But then again, its all about your own taste.

ghostdog74
+1  A: 

Neither is wrong.

The former is clearer to understand for someone reading the code.

Ask yourself if, when you are thinking about the problem you are trying to solve, the concepts that come to mind are closer to "if this, then that" or "a logical OR of two almost, but not quite, Boolean variables."

Oddthinking
+2  A: 

To me, the first idiom, the one using the explicit if, is preferable because more explicit.

However I've seen the or construct being referenced as the preferred / more pythonic one.

So, on the one hand, Explicit is better than implicit (Zen citation), on the other hand, the short expression can be viewed as pythonic (although shorter isn't equivalent to pythonic in all cases!)

A closely related SO question is most idiomatic way to convert None to empty string, and both the if and the or idioms were listed there.

mjv
+1  A: 

Both will eventually compile to the same code, given that or is a short-circuit operator (it doesn't evaluate the right hand argument if left hand is true).

I'd prefer the first one as it expresses your intent more clearly. The second one is probably more compact.

Johannes Rudolph
+1  A: 

The interpreter will likely execute them both the way. There are tradeoffs regarding code readability. Which statement is easier to recognize what it does? Certainly, the first is much clearer. For me, reading this post, I had to think more about the second one. I would use the first due to increased readability, even if the second statement is slightly 'sexier'.

Hope this helps.
-tjw

Travis J Webb
+4  A: 

When two style variations are so close stylistically, I use timeit as the tie-breaker: faster must mean closer to Python's mainstream, i.e., better. Hey, it's better than endless debate, y?-) So:

$ python -mtimeit -s'var=0; getvar=lambda:0' 'var = var or getvar()'
1000000 loops, best of 3: 0.359 usec per loop
$ python -mtimeit -s'var=0; getvar=lambda:0' 'if not var: var = getvar()'
1000000 loops, best of 3: 0.361 usec per loop
$ python -mtimeit -s'var=1; getvar=lambda:1' 'var = var or getvar()'
10000000 loops, best of 3: 0.123 usec per loop
$ python -mtimeit -s'var=1; getvar=lambda:1' 'if not var: var = getvar()'
10000000 loops, best of 3: 0.0899 usec per loop

the if has it -- equivalent when var is false, faster when it's true.

Alex Martelli
When nothing else matters, micro-optimize!
Chris Lutz
@Chris, I see it more as "find out what the Python mainstream is" -- Python core developers (me included) end up spending lots more time optimizing usage that's frequent and appreciated, rather than marginal and sneered at, so `timeit` is a way to capture the overall sum of their (our) efforts for an otherwise-moot decision.
Alex Martelli
seems a little contradictionary to me, how else did they implement short cicuiting then?
Johannes Rudolph
@Alex - My comment was meant to be more tongue-in-cheek than it reads. Forgive my amateur internet-sarcasm skills.
Chris Lutz
@Chris, sure, just wanted to clarify my reasoning. @Johannes, `x=x` doesn't get optimized away by the Python compiler, which is really a super-simple compiler, so the fact that the short-circuiting results in the equivalent of `var=var` does not make the latter "free"!-)
Alex Martelli
@Chris: I was the lone upvoter of your humorous one-liner. I'm surprised this didn't turn out to be a "famous comment" by now (shows how out of touch I'm with SO's zeitgeist). Funny bits lose something when analyzed, but essentially I loved its conciseness, its [obvious] un-serious nature (`who would imagine Alex as an advocate for micro-optimization ?`) and, most of all, the relief it provided on a serious, but none-the-less anecdotal topic. Fairly enough, when it comes to Python, Alex takes things seriously, at least by default.
mjv
+3  A: 

Actually, if you are trying to determine if var has been previously set using a call to get_var, then I would contend that both forms are wrong. Python treats a number of perfectly ordinary values as evaluating to a boolean 'false': 0, None, [], (,), set(), and {}. So let's say var is going to be an integer, and get_var() happens to return 0. Now, regardless of which form you use, get_var() will get called again and again, even though we already know that var is 0!

There are several methods for detecting whether a variable has been defined or not:

  • look in the dict returned by globals() or locals()

  • wrap the statement var = var in a try/except block, trapping on NameError

  • use a sentinel value like None, and initialize var to this value; then you can test for if var is None: var = get_var() (using 'is', not '=='). If you are unlucky, and None is a potential value to be returned from get_var(), then you'll need to define your own special not-yet-defined value, using something like NOT_DEFINED = object() and test for if var is NOT_DEFINED.

Paul McGuire