【问题标题】:Weird behavior of Value unpacking when splitting string in Python在 Python 中拆分字符串时值解包的奇怪行为
【发布时间】:2013-12-14 02:17:24
【问题描述】:

用例:我有一个由换行符分隔的长字符串,每行有两个由逗号分隔的元素。

理想情况下,这应该可以工作

[(x, y) for line in lines.split() for x, y in line.split(',')]

但它没有,并产生与下面相同的 ValueError。所以我试图分解问题以弄清楚这里发生了什么

lines = \
"""a,b
c,d
e,f
g,h"""

lines = [line for line in lines.split()]

print(lines)
print(len(lines))
print([len(line) for line in lines])
print(all(',' in line for line in lines))

[(x, y) for l in lines for x,y in l.split(',')]

产量:

/usr/bin/python3m /home/alex/PycharmProjects/test.py
['a,b', 'c,d', 'e,f', 'g,h']
4
[3, 3, 3, 3]
True

Traceback (most recent call last):
File "/home/alex/PycharmProjects/test.py", line 74, in <module>
...
File "/home/alex/PycharmProjects/test.py", line 63, in <listcomp>
[(x, y) for l in sines for x,y in l.split(',')]
ValueError: need more than 1 value to unpack

但是,如果我用经典的 for 循环替换最后一行中的列表推导:

for line in lines:
x, y = line.split(',')

执行成功:

['a,b', 'c,d', 'e,f', 'g,h']
4
True
[3, 3, 3, 3]
a b
c d
e f
g h

这简直让我发疯。如果我进一步分解它,我会发现列表、集合和生成器推导自己在尝试这样做:

[(x,y) for x, y in "a,b".split(",")]

有人知道为什么会发生这种情况吗?

【问题讨论】:

    标签: python string split list-comprehension


    【解决方案1】:

    这段代码:

    for x, y in "a,b".split(",")
    

    正在寻找 两个项目 位于 内部 "a,b".split(",") 返回的可迭代对象(列表)的迭代对象。

    但是,它只找到'a''b'

    >>> "a,b".split(",")
    ['a', 'b']
    >>>
    

    由于这两个都只是 单项 可迭代(只有一个字符的字符串),因此代码会中断。


    考虑到上述情况,观察在逗号的每一侧添加一个额外字符时会发生什么:

    >>> "ax,by".split(",")
    ['ax', 'by']
    >>> [(x,y) for x, y in "ax,by".split(",")]
    [('a', 'x'), ('b', 'y')]
    >>>
    

    如您所见,代码现在可以运行了。

    这是因为"ax,by".split(",") 返回一个包含两项可迭代项(具有两个字符的字符串)的可迭代项(列表)。此外,这正是for x, y in 所寻找的。​​p>


    但是,您也可以将最后一部分放在一个元组中:

    >>> ("a,b".split(","),)
    (['a', 'b'],)
    >>> [(x,y) for x, y in ("a,b".split(","),)]
    [('a', 'b')]
    >>>
    

    ("a,b".split(","),) 返回一个包含两项可迭代对象(一个包含两个字符串的列表)的可迭代对象(元组)。再一次,这正是 for x, y in 正在寻找的,所以代码有效。


    考虑到所有这些,以下应该可以解决您的问题:

    [(x, y) for line in lines.split() for x, y in (line.split(','),)]
    

    【讨论】:

    • 感谢您解释为什么我的假设是错误的。欣赏它:)
    【解决方案2】:

    为什么不这样?

    [tuple(l.split(',')) for l in lines ]
    

    l.split(',') 只为每个 l 生成两个项目,而不是每个 l 的两个项目的可迭代

    【讨论】:

    • 当然,我可以这样做,但它破坏了元组解包的意义,特别是如果我想对某些元素进行操作而不必打破括号和索引:)
    【解决方案3】:

    为什么不只是:

    lines = """
    a,b
    c,d
    e,f
    g,h
    """
    
    lines = [line for line in lines.split()]
    
    print(lines)
    print(len(lines))
    print([len(line) for line in lines])
    print(all(',' in line for line in lines))
    
    [l.split(",") for l in lines]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多