10

What's the most pythonic way to take the single item of a 1-sized list in python?

I usually go for

item = singlet_list[0] 

This would fail for an empty list, but I would like a way to make it fail even if the list is longer, something like:

assert(len(singlet_list) == 1) item = singlet_list[0] 

but I find this ugly. Is there anything better?

2
  • what happens if the list is empty or has more than one item? Commented Jul 21, 2014 at 16:40
  • @PadraicCunningham for my use case I'd like it to fail loudly in the case this happens. My point here was that, if the list is longer, the first option does something and works (implicitly makes a choice selecting the first in the sequence). The second snippet, instead, fails loudly for both too long and too short inputs, but it is on 2 lines and somewhat brakes the flow of the code. Commented Jul 21, 2014 at 23:58

2 Answers 2

16

This blog post suggests an elegant solution I fell in love with:

(item,) = singlet_list 

I find it much more readable, and plus it works with any iterable, even if it is not indexable.

EDIT: Let me dig a little more

This construct is called sequence unpacking or multiple assignment throughout the python documentation, but here I'm using a 1-sized tuple on the left of the assignment.

This has actually a behaviour that is similar to the 2-lines in the initial question: if the list/iterable singlet_list is of length 1, it will assign its only element to item. Otherways, it will fail with an appropriate ValueError (rather than an AssertionError as in the question's 2-liner):

>>> (item,) = [1] >>> item 1 >>> (item,) = [1, 2] ValueError: too many values to unpack >>> (item,) = [] ValueError: need more than 0 values to unpack 

As pointed out in the blog post, this has some advantages:

  • This will not to fail silently, as required by the original question.
  • It is much more readable than the [0] indexing, and it doesn't pass unobserved even in complex statements.
  • It works for any iterable object.
  • (Of course) it uses only one line, with respect to explicitly using assert
Sign up to request clarification or add additional context in comments.

5 Comments

This method will still fail for empty lists. ValueError: need more than 0 values to unpack
By the way, I was amazed by this solution, but I'll wait some time before accepting it, in case someone comes up with something even better
@Cyber Which is not a problem at all. When the list is empty, there isn't a value to extract.
@Davide I edited it with a way to avoid the ValueError if the list is empty.
@Cyber this was actually the point: don't fail silently if anything goes wrong and the list/sequence has more than 1 value.
3

You could use an inline if...else and define a default value like this:

If singlet_list contains one or more values:

singlet_list = [2] item = singlet_list[0] if singlet_list else False print item 

output:

2 

If singlet_list is empty:

singlet_list = [] item = singlet_list[0] if singlet_list else False print item 

output:

False 

This uses the fact that an empty list evaluates to False.


Similarly, if you would like a default value to be assigned if the list doesn't contain exactly one element, you could check the length:

item = singlet_list[0] if len(singlet_list) == 1 else False 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.