views:

150

answers:

3

One of the ideas of Python's design philosophy is "There should be one ... obvious way to do it." (PEP 20), but that can't always be true. I'm specifically referring to (simple) if statements versus boolean evaluation. Consider the following:

if words:
    self.words = words
else:
    self.words = {}

versus

self.words = words or {}

With such a simple situation, which is preferable, stylistically speaking? With more complicated situations one would choose the if statement for readability, right?

+9  A: 

"There should be only one" can perfectly well always be true; it's the positive assertion "there is only one" that cannot be -- "should" implies a target, a goal, not the possibility of always reaching it (e.g., for numbers a and b, forbidding either b + a or a + b would be so absurd that there just cannot sensibly be "only one way" in this case).

In your example, I would agree that the or is preferable in sufficiently simple cases (four lines to do what can be done in one clear and readable line is a waste of vertical space) but not for a predicate of any significant complexity. Deciding what has "significant complexity" is, of course, a judgment call.

Alex Martelli
A: 

(Edited)
well in a case like below, i vote for the conditional expression

def somesuch(self, words=None):
    self.words = words or {}
    ...

of course, if you think that'd improve readability (you can read it aloud that way?), you can try

self.words = words if words else {}
Nas Banov
You're right! In fact, this whole question was inspired by trying to do that with a class definition and finding all of my instances shared the same dictionary attribute.
mkscrg
-1: You probably don't want to do this (at least not in general) - mutable default arguments can surprise you. See http://stackoverflow.com/questions/1132941/ for example.
Scott Griffiths
@Scott Griffiths: ugh, sorry. i haven't suffered that yet i guess since i did not think of it. thanks for the URL. so **no mutable default arguments** in python. keep the -1, hope that helps me remember the lesson
Nas Banov
@Scott: are you downvoting this answer because mentioning a practice that has nothing to do with the question? Do you actually mean "you don't want to do default arguments"?
xtofl
@xtoll: i had `def somesuch(self, words=[]):` initially, forgetting that it is evil. had edited the post since then
Nas Banov
+1  A: 

In this case I'd say "Explicit is better than implicit".

When someone reads your code, they can make a few assumptions. They can assume that "words" can be either an empty dict or one with data in it (missing the case when it is None) In that case, they might be tempted to optimize your code. They might even be right to do it, if it isn't stated anywhere that you can get a None value.

If "words" can in fact be None, I'd try to be clear about that with:

self.words = words
if words is None:
    self.words = {}

Or possibly an "else" instead of unconditional assignment first. In any case, this way you sort of document the fact that None is an expected value for "words".

Mattias Nilsson