在解包时是否可以指定默认值?

22

我有以下内容:

>>> myString = "has spaces"
>>> first, second = myString.split()
>>> myString = "doesNotHaveSpaces"
>>> first, second = myString.split()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: need more than 1 value to unpack
如果字符串中没有空格,我希望second默认为None。我目前有以下代码,但想知道是否可以在一行内完成:

如果字符串中没有空格,我希望second默认为None。我目前有以下代码,但想知道是否可以在一行内完成:

splitted = myString.split(maxsplit=1)
first = splitted[0]
second = splitted[1:] or None

据我所知,这是不可能的,因为分割函数就是这样编写的。但是你可以使用一个if语句来判断字符串中是否有空格。 - stuck
5个回答

29

我建议您考虑使用另一种方法,即partition而不是split

>>> myString = "has spaces"
>>> left, separator, right = myString.partition(' ')
>>> left
'has'
>>> myString = "doesNotHaveSpaces"
>>> left, separator, right = myString.partition(' ')
>>> left
'doesNotHaveSpaces'
如果您使用的是Python3,您就有这个选项可用:
>>> myString = "doesNotHaveSpaces"
>>> first, *rest = myString.split()
>>> first
'doesNotHaveSpaces'
>>> rest
[]

太好了! :) 正确的工具完成任务。 - Bálint Sass

6
一种通用的解决方案是将可迭代对象与 None 值的 repeat 链接起来,然后使用结果的 islicechain
from itertools import chain, islice, repeat

none_repat = repeat(None)
example_iter = iter(range(1)) #or range(2) or range(0)

first, second = islice(chain(example_iter, none_repeat), 2)

这将使用None填充缺失的值。如果您经常需要此类功能,可以将其放入以下函数中:

def fill_iter(it, size, fill_value=None):
    return islice(chain(it, repeat(fill_value)), size)

尽管最常见的用法是字符串,这就是为什么 str.partition 存在的原因。


6
这里有一个通用的解决方法,可以展开元组并在元组长度不足时使用默认值:
unpacker = lambda x,y=1,z=2:(x,y,z)

packed = (8,5)
a,b,c = unpacker(*packed)
print(a,b,c) # 8 5 2

packed = (8,)
a,b,c = unpacker(*packed)
print(a,b,c) # 8 1 2

点击此链接可以试玩这段代码


0
这里的回答确实有一些... 呃,有趣。
def fixed_width_split(s: str, delim: str, n: int, fill: Any = None):
    raw_split = s.split(delim)

    return raw_split[:n] + [fill] * (n - len(raw_split))

让我们试试看:
>>> fixed_width_split("1:2:3", ":", 4)
['1', '2', '3', None]

>>> fixed_width_split("1:2:3", ":", 2)
['1', '2']

>>> fixed_width_split("1:2:3", ":", 5, fill=0)
['1', '2', '3', 0, 0]

所以在需要将其解包为固定数量的值并确保能够解包的情况下,您可以使用它。
a, b, c = fixed_width_split(mystr, ":", 3)

一些关于有些晦涩语法的细节。
# take at most `n` elements from the original split.
parts[:n]

# make an array of x elements with value fill
[fill] * x 
[1] * 3 == [1, 1, 1]

# negative values are equivalent to 0.
[1] * -2 == []

# find the difference between the target length and the length of the original split.
n - len(parts)

-1
你可以尝试这个:
NUM2UNPACK=2   
parts = myString.split()    
first, second = parts+[None]*(NUM2UNPACK-(len(parts)))     

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接