I've often been frustrated by the lack of flexibility in Python's iterable unpacking. Take the following example:
a, b = "This is a string".split(" ", 1)
Works fine. a
contains "This"
and b
contains "is a string"
, just as expected. Now let's try this:
a, b = "Thisisastring".split(" ", 1)
Now, we get a ValueError
:
ValueError: not enough values to unpack (expected 2, got 1)
Not ideal, when the desired result was "Thisisastring"
in a
, and None
or, better yet, ""
in b
.
There are a number of hacks to get around this. The most elegant I've seen is this:
a, *b = mystr.split(" ", 1)
b = b[0] if b else ""
Not pretty, and very confusing to Python newcomers.
So what's the most Pythonic way to do this? Store the return value in a variable and use an if block? The *varname
hack? Something else?
This looks perfect for str.partition:
>>> a, _, b = "This is a string".partition(" ")
>>> a
'This'
>>> b
'is a string'
>>> a, _, b = "Thisisastring".partition(" ")
>>> a
'Thisisastring'
>>> b
''
>>>
How about adding the default(s) at the end and throwing away the unused ones?
>>> a, b, *_ = "This is a string".split(" ", 1) + ['']
>>> a, b
('This', 'is a string')
>>> a, b, *_ = "Thisisastring".split(" ", 1) + ['']
>>> a, b
('Thisisastring', '')
>>> a, b, c, *_ = "Thisisastring".split(" ", 2) + [''] * 2
>>> a, b, c
('Thisisastring', '', '')
Similar (works in Python 2 as well):
>>> a, b, c = ("Thisisastring".split(" ", 2) + [''] * 2)[:3]
>>> a, b, c
('Thisisastring', '', '')
The *varname
hack seems very pythonic to me:
Similar to how function parameters are handled
Lets you use a one-liner or if block or nothing to correct type of the element if desired
You could also try something like the following if you don't find that clear enough for new users
def default(default, tuple_value):
return tuple(map(lambda x: x if x is not None else default, tuple_value))
Then you can do something like
a, *b = default("", s.split(...))
Then you should be able to depend on b[0] being a string. I fully admit that the definition of default is obscure, but if you like the effect, you can refine until it meets your aesthetic. In general this is all about what feels right for your style.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With