Pythonic style
Frank Millman
frank at chagford.com
Mon Sep 21 10:44:19 EDT 2020
On 2020-09-21 3:46 PM, Chris Angelico wrote:
> On Mon, Sep 21, 2020 at 11:37 PM Tim Chase
> <python.list at tim.thechases.com> wrote:
>>
>> On 2020-09-20 18:34, Stavros Macrakis wrote:
>>> Consider a simple function which returns the first element of an
>>> iterable if it has exactly one element, and throws an exception
>>> otherwise. It should work even if the iterable doesn't terminate.
>>> I've written this function in multiple ways, all of which feel a
>>> bit clumsy.
>>>
>>> I'd be interested to hear thoughts on which of these solutions is
>>> most Pythonic in style. And of course if there is a more elegant
>>> way to solve this, I'm all ears! I'm probably missing something
>>> obvious!
>>
>> You can use tuple unpacking assignment and Python will take care of
>> the rest for you:
>>
>> >>> x, = tuple() # no elements
>> Traceback (most recent call last):
>> File "<stdin>", line 1, in <module>
>> ValueError: not enough values to unpack (expected 1, got 0)
>> >>> x, = (1, ) # one element
>> >>> x, = itertools.repeat("hello") # 2 to infinite elements
>> Traceback (most recent call last):
>> File "<stdin>", line 1, in <module>
>> ValueError: too many values to unpack (expected 1)
>>
>> so you can do
>>
>> def fn(iterable):
>> x, = iterable
>> return x
>>
>> The trailing comma can be hard to spot, so I usually draw a little
>> extra attention to it with either
>>
>> (x, ) = iterable
>>
>> or
>>
>> x, = iterable # unpack one value
>>
>> I'm not sure it qualifies as Pythonic, but it uses Pythonic features
>> like tuple unpacking and the code is a lot more concise.
>
> Or:
>
> [x] = iterable
>
> I'd definitely recommend using unpacking as the most obvious way to do
> this. Among other advantages, it gives different messages for the "too
> many" and "too few" cases.
>
I used something similar years ago, but I made the mistake of relying on
the error message in my logic, to distinguish between 'too few' and 'too
many'. Guess what happened - Python changed the wording of the messages,
and my logic failed.
After messing about with some alternatives, I ended up with the OP's
first option (with some added comments), and have stuck with it ever
since. It is not pretty, but it is readable and unambiguous.
Frank Millman
More information about the Python-list
mailing list