【问题标题】:Too many values to unpack with function in python?在 python 中使用函数解包的值太多?
【发布时间】:2013-10-08 12:53:37
【问题描述】:

我有这样的文字:

text = ["A/abc","B/abd","C/abc","D/xyz"]

我想要的输出是

 mylist1 = ["A","C"]
 mylist2 = ["B"]
 mylist3 = ["D"]

我正在寻找的唯一标签是“/abc”和“/abd”

我现在拥有的是:

def searchWord(segment):
    word_tag = segment.split('/')

    if re.finditer('ab',word_tag[1]):
        if re.finditer('abc',word_tag[1]):
            letter = word_tag[0]
            mylist1 = letter
        else:
            letter = word_tag[0]
            mylist2 = letter
    else:
        letter = word_tag[0]
        mylist3 = letter

    return mylist1
    return mylist2
    return mylist3

mylist1,mylist2,mylist3 = [searchWord(segment) for segment in text]

它似乎工作正常,但抛出异常:

 ValueError: too many values to unpack.

我的“文本”列表相当大,这可能是问题吗?在为此过程构建函数之前,我没有遇到此问题。

谢谢!

【问题讨论】:

  • 由于 text 有 4 个项目,因此列表理解也将如此。目前尚不清楚如何使用列表推导将其减少为一个 3 项列表,您可以将其解压缩到三个列表中。修复 searchWord 以返回一个元组不会解决这个问题。
  • @chepner 你能详细说明一下吗?我不确定我是否理解...
  • text 有 4 个项目,因此 searchWord 将被调用 4 次,您的列表理解也将包含 4 个项目。您不能使用列表推导来执行您似乎想要的那种缩减(即[ 'a', 'b', 'c', 'd' ] -> [ ['a', 'b'], 'c', 'd' ])。

标签: python list error-handling


【解决方案1】:

将您的列表作为元组返回:

return mylist1, mylist2, mylist3

Python 不会执行所有三个return 语句,只执行第一个。

如果您尝试将项目分类为不同的类别,通常会使用字典:

buckets = {'abc': [], 'abd': [], 'xyz': []}
for segment in text:
    item, tag = segment.split('/', 1)
    buckets[tag].append(item)

您仍然可以将这三个列表提取为 3 个变量,但您也可以直接引用存储桶。例如,您可以参考buckets['abc'],而不是mylist1

【讨论】:

  • 应该是return (mylist1, mylist2, mylist3)吧?
  • @KDawG:逗号构成元组,而不是括号。
  • @Wooble 刚刚测试,看起来它们都产生相同的结果:)
  • 我想你明白了。我遇到了一个不同的错误,但我现在知道如何处理这个错误。我是新手,对元组并不完全熟悉,所以我需要阅读这些内容。谢谢!
  • 这并不能解决问题,甚至不是问题的原因,也不能帮助 OP 得到他想要的解决方案。请注意,他希望每次迭代都根据其内容附加到 3 个不同的列表……这种方法是完全错误的。
【解决方案2】:

您的问题

您确实应该包含完整的堆栈跟踪,但在这种情况下很容易推断出 mylist1,mylist2,mylist3 = [searchWord(segment) for segment in text] 是有问题的行,因为列表理解返回超过 3 个值,您不能只将它们分配给 3变量。但是您的代码中的问题是您多次尝试return

return mylist1
return mylist2
return mylist3

一个函数只能有 1 个返回值,所以你应该将其更改为:

return (mylist1, mylist2, mylist3)

解决方案

在查看您的代码并看到您的愿望之后。我帮你修好了:

def catagorize(data):
    container = [[],[],[]]
    for segment in data:
        searchWord(segment, container)
    return container

def searchWord(segment, container):
    letter, tag = segment.split('/')
    if tag == 'abc':
        container[0].append(letter)
    elif tag == 'abd':
        container[1].append(letter)
    elif tag == 'xyz':
        container[2].append(letter)
    else:
        raise ValueError('unknown tag')

运行代码:

>>> text = ["A/abc","B/abd","C/abc","D/xyz"]
>>> mylist1, mylist2, mylist3 = catagorize(text)
>>> print mylist1, mylist2, mylist3 
['A', 'C'] ['B'] ['D']

另一种解决方案

更强大的解决方案:

from collections import defaultdict

def catagorize(data):
    container = defaultdict(list)
    for letter, tag in (segment.split('/') for segment in data):
        container[tag].append(letter)
    return container

在行动:

>>> catagorize(["A/abc","B/abd","C/abc","D/xyz"])
defaultdict(<type 'list'>, {'xyz': ['D'], 'abc': ['A', 'C'], 'abd': ['B']})

【讨论】:

    【解决方案3】:

    只执行第一个returnreturn 返回一个答案并且它将控制权返回给调用者。之后的任何回报都不会运行。

    因此,您不会按预期返回三项,而只返回 mylist 的内容(显然不是三项列表)。

    你想要什么:

    return (mylist1, mylist2, mylist3)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-18
      • 1970-01-01
      • 1970-01-01
      • 2018-03-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多