def get_single(l):
assert l and len(l) == 1
return l[0]
Then you get the best of both worlds: readability and a concise one-liner. def get_single(l):
assert l and len(l) == 1
return l[0]
Then you get the best of both worlds: readability and a concise one-liner. def get_single(l):
i = iter(l)
val = i.next()
try:
i.next() # expected to throw exception for one-element iterable
except StopIteration:
return val
raise AssertionError('More than one object')
Eww. assert s and len(s)==1
return s.pop()
Or if you want to stay in the immutable land: assert s and len(s)==1
return tuple(s)[0] >>> x = (lambda: (yield 1))() # generator with one step
>>> y = tuple(x)[0]
>>> y
1
>>> list(x) # exhausted
[]
>>> x = (lambda: (yield 1))()
>>> y, = x
>>> y
1
>>> list(x) # exhausted, too!
[]
Because that's just what you inevitably need to do to fetch a value from a generator. There is no peeking action or some such.Also, the performance here is probably much worse. (Although in many cases it would not matter.)
But that's just my opinion, your suggestion is legitimate.
This is an argument against using functions at all. If it works against get_single, it works against all functions.
That is to say, it doesn't work at all.
A function that squares a number is simple, one that computes the standard deviation is definitely more complex.
I'm talking about the complexity difference between this:
def stddev(pop):
total = 0
count = 0
for x in pop:
total += x
count += 1
mean = total / float(count)
variance = 0
for x in pop:
variance += (x - mean)**2
return math.sqrt(variance)
and this: def stddev(pop):
return math.sqrt(variance(pop))
def variance(pop):
m = mean(pop)
return sum(square(x - m) for x in pop)
def mean(pop):
return sum(pop) / float(len(pop))
def square(x):
return x**2
The first is a (mildly) complex function. The latter are all simple functions, and the complex result is constructed by composing simple operations.Good programmers write functions in the latter style, not the former.
Well, that stddev function could be much less verbose:
def stddev(pop):
mean = sum(pop) / float(len(pop))
variance = sum( (x-mean)**2 for x in pop)
return math.sqrt(variance)
To me that's easier to read than jumping back and forth between multiple function definitions. Of course, if you need the mean or variance independently then your way is better.Sure, it could, but I was demonstrating what it looked like without the use of functions. Your example proves my point just as mine does: sum(), like mean() or variance() in my example, is just a simple function, the kind that I'm arguing for. The fact that it's built into Python (rather recently, I note) doesn't change that fact or reduce the impact of the argument. Your example simply goes one step down the path, and mine goes further.
> To me that's easier to read than jumping back and forth between multiple function definitions.
You don't have to jump back and forth between function definitions. Let's say you don't know what the standard deviation is, but you know what the mean is. You can look at the definition of stddev() and see, "Ah, it's clearly the sqrt() of the variance. What's the variance? Ah, it's the sum of the squares of difference between each element and the mean." You know what the mean() does (its name is pretty clear) and you know what sum() and square() do, so you never have to look at those functions. Someone else who knows what the variance is would never have to look that deep. When someone is reading the stddev() in my example, he doesn't have concern himself with implementation details of functions he already understands. When someone is reading yours, he has to at least read how the mean is calculated. He can't avoid it--it's right there.
> Of course, if you need the mean or variance independently then your way is better.
You almost certainly will in any case where you're using the standard deviation, but that's just an artifact of the example. Other advantages of using small, simple functions like in my example:
* More reusable (as you noted) * More easily testable. * More easily comprehensible (as I showed above) * More easily documented (especially in a language like Python with its docstring support) * More conceptual abstraction
This is redundant: if a list's length is 1, then it's true in a boolean context.
Also, please stop naming your lists 'l'. On a vast array of fonts, it differs only in a few pixels from '1'. Use "L" instead :)
assert l is not None and len(l) == 1And as was mentioned the "assert l" part is defending against l being None. I suppose I could be more explicit by saying "assert l is not None and len(l) == 1".
I'm not sure why you'd defend against None anyway. Why defend against None, but not against 3.1459 or 4j or ''?
He's defending against None because calling __len__ on None results in an exception.
3.14159 also results in an exception but it's far more likely that the object passed was None than that it was a completely different type than the one expected.
FYI, None is a completely different type than the one expected.
In a boolean context, the list is true if the length is non-zero. This example and the one the article is about is for the case where you know the list to have exactly one element. Not zero and not more than one.
The `if L and` part safeguards against that.
Use xs. If you have multiple lists use ys etc.
This has multiple benefits over L in terms of readability anad understandability as a single-item variable names can be made to match the list naming scheme:
for x in xs:
for y in ys:
do_some_fancy_calculation(x,y)