Live data from Hacker News

Python idiom for taking the single item from a list

blog.garlicsim.org

91–97 of 97 posts

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

#91
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 :)

There's a better variable naming scheme for generic lists:

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)

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

#92
post #2

Excellent. That one belongs in any Python style guide. Though technically it's not a style, it does lead to better readability, and reduces the propensity for unforseen consequences.

The reason it's not in the Python style guide is because it's a symptom of other problems in code. Lists are for holding multiple values of the same type. If you know that a list will always have one and only one value, it's not conceptually a list, it's some other type that's been encoded into a list for some reason, and you should fix that conceptual mismatch rather than papering over the issue with a style idiom.

What you say sounds right, but it's not. Using some DB APIs you'll get back a list of results, and you'll know from the SQL that it will only have one result.

Another example is if you know there is a single item in a data structure, and use list comprehension to extract it. You'll end up with a list of one item.

These situations happen, and for good reasons.

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

#93

Earlier quoted context omitted.

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.

A property which is exposed by the article's solution too:

   >>> 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.

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

#94
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.

Create a wrapper function for a one-line statment? Sure, it's more readable, but it's Unpythonic.

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

#95

Earlier quoted context omitted.

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.

And the point that was made in the other branch of this thread is that if the author intends to guard against None (who knows why?) then he should say, explicitly, "if L is not None". That's what PEP8 recommends precisely to avoid ambiguities such as these.

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

#96

Earlier quoted context omitted.

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.

> 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.

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

#97
post #46
post #37

I prefer array.single(), I think it's a rare enough use-case that spelling out what you are doing is worthwhile.

Are you talking about another language? 1) In python, arrays and lists are two very different things. 2) Neither the array module nor the array class have a single function.

The example came to mind via C#. I assumed that it could be added to Python via a mixin or whatever if you wanted to do it there.
Post reply on HN