ValueError:在Python 2.6.6中解包需要超过两个值

17 投票
4 回答
102747 浏览
提问于 2025-04-16 14:54

我在运行单元测试时遇到了一个错误:ValueError: 需要更多的值来解包,所以有两个测试失败了,一个被跳过了。根据我所了解的情况,

lambda i: get_error_count(self._error_lookup, i))

源代码的第142行是这个方法。

for test, err, capt in errors:

里面有一行代码:

count = get_error_count(i)

参考 Python 3.0 有点像这样。多余的值可以作为列表绑定到最后一个变量上:

a,b,*c = [1,2,3,4,5]

这样会导致 c 里面包含 [3,4,5]。

在 Python 2.x 中,你不能直接这样做,但你可以创建一个函数,把输入的参数元组调整到正确的长度,这样你就可以这样做:

a,c,b = fix(1,2)
d,e,f = fix(1,2,3,4)

不过,这个函数并不知道左边变量的长度,所以必须把它作为额外的参数传入,或者直接写死在代码里。

所以,

count = get_error_count(i)
uses only one variable, where as
def get_error_count(lookup, index):
takes on 2

我应该用什么作为第二个变量来解决这个问题呢?

谢谢,
-Kamal。

-------------------- >> 开始捕获的标准输出 << ---------------------

\ test_many_errors.test_assert_one ... 失败 test_many_errors.test_one ... 成功 test_many_errors.test_assert_two ... 错误 test_many_errors.test_two ... 成功 test_many_errors.test_value_one ... 错误 test_many_errors.test_value_two ... 跳过: (, ValueError(), ) test_many_errors.test_good_one ... 成功 test_many_errors.test_good_two ... 成功

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/Current/bin/nosetests", line 10, in <module>
    sys.exit(run_exit())
  File "/Library/Frameworks/Python.framework/Versions/6.3/lib/python2.6/site-packages/nose/core.py", line 117, in __init__
    **extra_args)
  File "/Library/Frameworks/Python.framework/Versions/6.3/lib/python2.6/unittest.py", line 817, in __init__
    self.runTests()
  File "/Library/Frameworks/Python.framework/Versions/6.3/lib/python2.6/site-packages/nose/core.py", line 196, in runTests
    result = self.testRunner.run(self.test)
  File "/Library/Frameworks/Python.framework/Versions/6.3/lib/python2.6/site-packages/nose/core.py", line 63, in run
    result.printErrors()
  File "/NOSE_TRIM/nosetrim-read-only/nosetrim/nosetrim.py", line 136, in printErrors
    lambda i: get_error_count(self._error_lookup, i))
  File "/NOSE_TRIM/nosetrim-read-only/nosetrim/nosetrim.py", line 142, in printErrorList
    for test, err, capt in errors:
ValueError: need more than 2 values to unpack

/

--------------------- >> 结束捕获的标准输出 << ----------------------


总共运行了 3 个测试,耗时 1.263 秒

4 个回答

1

你可以写一个工具函数来让你的结果保持一致:

def do_something2():
    return 1, 2

def do_something3():
    return 1, 2, 3

def do_something5():
    return 1, 2, 3, 4, 5

def uniform_result(*args):
    return args[0], args[1], args[2:]

a, b, c =  uniform_result(*do_something2())
print a, b, c
# 1 2 ()

a, b, c =  uniform_result(*do_something3())
print a, b, c
# 1 2 (3,)

a, b, c =  uniform_result(*do_something5())
print a, b, c
# 1 2 (3, 4, 5)
2

这里的 errors 是一个列表,里面的每个项目都是长度为2或3的元组。你想在一个循环中解包这些不同长度的元组。正如你所注意到的,在Python2中没有简单的方法来做到这一点。与其想出一个聪明的办法来实现这个功能,我建议你确保你的 errors 列表里的元组长度始终为3。这可以在你每次添加项目到 errors 时做到,或者事后处理,比如这样:

errors = [(x[0], x[1], x[2]) if len(x) == 3 else (x[0], x[1], None) for x in errors]

或者你可以创建一个生成器(这有点违背我之前的建议,不要找聪明的方法来实现这个功能):

def widen_tuples(iter, width, default=None):
    for item in iter:
        if len(item) < width:
            item = list(item)
            while len(item) < width:
                item.append(default)
            item = tuple(item)
        yield item

这样使用:

>>> errors = [(1, 2), (1, 2, 3)] 
>>> for a, b, c in widen_tuples(errors, 3):
...     print a, b, c
1 2 None
1 2 3
20
a, b, c = do_something()
t = do_something()
# t is now a tuple (or list, or whatever was returned) of results
if len(t) > 2:
    # Can use the third result!
    c = t[2]

与其在赋值时拆开变量,不如试着把结果赋值给一个单独的变量,然后检查这个变量的长度。

撰写回答