Live data from Hacker News

Python idiom for taking the single item from a list

blog.garlicsim.org

81–90 of 97 posts

Re: Python idiom for taking the single item from a list

#81

Earlier quoted context omitted.

It is certainly okay for some functions to be complex. Some may rely on simpler functions, but the one you'd use can still do a complex task in general. A function that squares a number is simple, one that computes the standard deviation is definitely more complex.

> 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 var…

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.

Re: Python idiom for taking the single item from a list

#82
post #65

Earlier quoted context omitted.

I wouldn't name a list l in real code. It was just the first thing that popped to mind. :-) And 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".

Yes, you should definitely should be more explicit if that's what you intend to check: PEP8 makes that explicit. I'm not sure why you'd defend against None anyway. Why defend against None, but not against 3.1459 or 4j or ''?

There's nothing wrong with `is l`. Sounds like you're just splitting hairs.

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.

Re: Python idiom for taking the single item from a list

#83
post #47

Personally, I think this is a bit on the "clever" side. Plus, the error message you get isn't as easy to understand as if you used an assert statement. I'd probably just do something like this: 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.

> assert l and len(l) == 1 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 :)

This is redundant: if a list's length is 1, then it's true in a boolean context.

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.

Re: Python idiom for taking the single item from a list

#84

Earlier quoted context omitted.

> 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 var…

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 bette…

> Well, that stddev function could be much less verbose:

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

Re: Python idiom for taking the single item from a list

#85

Earlier quoted context omitted.

You don't need to do that for a set. sets support `len()`. Also set supports `pop()`, so the code is very similar to the list one: 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]

Both of those still fail for other non-list iterables, like generators.

They also have the side effect of removing an item from the collection.

Re: Python idiom for taking the single item from a list

#87

Earlier quoted context omitted.

> assert l and len(l) == 1 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 :)

This is redundant: if a list's length is 1, then it's true in a boolean context. 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.

You are aware that asserting `len(L) == 1` excludes the possibility that it's empty, right? You know what "redundant" means, right?

Re: Python idiom for taking the single item from a list

#89

Proposed style guide: When you want to get the (n+1)th item from a list, do: item = stuff[n] To get the first item, do: item = stuff[0] Unless the list has one element, then do: (item, ) = stuff At least you'll never be accused of consistency.

I'm annoyed by the belief that consistency is ipso facto good. Consistency is a tool for attacking a particular type of problem. Consistency for its own sake will often make things worse.

I see this fallacious reasoning all the time in design critiques: this is inconsistent with that. Well, yes, but so what? Why is consistency desirable in this instance?

Re: Python idiom for taking the single item from a list

#90

Earlier quoted context omitted.

This is redundant: if a list's length is 1, then it's true in a boolean context. 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.

You are aware that asserting `len(L) == 1` excludes the possibility that it's empty, right? You know what "redundant" means, right?

if L is None then asserting `len(L)==1` throws an exception.

The `if L and` part safeguards against that.

Post reply on HN