Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonic way to get the single element of a 1-sized list

Tags:

python

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?

like image 908
Davide Avatar asked Jul 21 '14 16:07

Davide


2 Answers

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
like image 87
Davide Avatar answered Oct 09 '22 11:10

Davide


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
like image 3
Tom Fenech Avatar answered Oct 09 '22 12:10

Tom Fenech