88
votes

When a Python list is known to always contain a single item, is there a way to access it other than:

mylist[0]

You may ask, 'Why would you want to?'. Curiosity alone. There seems to be an alternative way to do everything in Python.

2
There may be alternatives, but there's usually only one obvious way to do it - and, in this case, you seem to have already found it. - ekhumoro
if it always contains a single item, then maybe a list is not the best data type? - David Zemens
@ekhumoro: I'm actually partial to the sequence unpacking method, because it verifies the assumption that the sequence only has one element. mylist[0] succeeds when you have at least one element, but doesn't complain if you actually had 30 elements. singleitem, = mylist verifies that you've got exactly one element, no more, no less. - ShadowRanger
@ShadowRanger. The question is explicitly about accessing the only element in a list which is already known to contain a single item. - ekhumoro
@ekhumoro: No disagreement. I just prefer to program defensively, so violations of requirements don't pass silently (sure it fails, but it fails loudly, which is much easier to identify and fix than subtle misbehaviors). If I had a nickel for every time some "known" behavior in production code turned out to be dead wrong... Well, I probably wouldn't be rich, but I'd be able to take the family out to a really nice dinner. - ShadowRanger

2 Answers

138
votes

Sequence unpacking:

singleitem, = mylist
# Identical in behavior (byte code produced is the same),
# but arguably more readable since a lone trailing comma could be missed:
[singleitem] = mylist

Explicit use of iterator protocol:

singleitem = next(iter(mylist))

Destructive pop:

singleitem = mylist.pop()

Negative index:

singleitem = mylist[-1]

Set via single iteration for (because the loop variable remains available with its last value when a loop terminates):

for singleitem in mylist: break

Many others (combining or varying bits of the above, or otherwise relying on implicit iteration), but you get the idea.

19
votes

I will add that the more_itertools library has a tool that returns one item from an iterable.

from more_itertools import one


iterable = ["foo"]
one(iterable)
# "foo"

In addition, more_itertools.one raises an error if the iterable is empty or has more than one item.

iterable = []
one(iterable)
# ValueError: not enough values to unpack (expected 1, got 0)

iterable = ["foo", "bar"]
one(iterable)
# ValueError: too many values to unpack (expected 1)

more_itertools is a third-party package > pip install more-itertools