Safely unpacking results of str.split [duplicate]

三世轮回 提交于 2019-12-19 08:04:08

问题


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?


回答1:


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
''
>>>



回答2:


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', '', '')



回答3:


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.



来源:https://stackoverflow.com/questions/44609040/safely-unpacking-results-of-str-split

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!