Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 有没有办法抓住一个;“值太多,无法解包”;错误?_Python - Fatal编程技术网

Python 有没有办法抓住一个;“值太多,无法解包”;错误?

Python 有没有办法抓住一个;“值太多,无法解包”;错误?,python,Python,我的tuple子类的用法如下: class MyTuple(tuple): def __new__(cls, columns=()): return tuple.__new__(cls, tuple(columns)) a, b = MyTuple(columns=('hello', 'world', 42)) 给出以下例外情况: Traceback (most recent call last): File "<stdin>", line 6, in

我的tuple子类的用法如下:

class MyTuple(tuple):
    def __new__(cls, columns=()):
        return tuple.__new__(cls, tuple(columns))

a, b = MyTuple(columns=('hello', 'world', 42))
给出以下例外情况:

Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
ValueError: too many values to unpack
那似乎很不雅观。。有什么方法可以覆盖元组解包引发的异常吗

更新:实际用例如下

>>> dice = FactSet()
>>> for i in range(1, 7):
...     dice.add('dice', n=i)
...
>>> print dice.n + dice.n == 10   # give me all combinations that add up to 10
XPROD((dice(n=4), dice(n=6))
      (dice(n=5), dice(n=5))
      (dice(n=6), dice(n=4)))
>>> a, b = dice.n + dice.n == 10  # same as above, but unpack the individual die
>>> a
FactSet([
    dice(n=4),
    dice(n=5),
    dice(n=6),
])
>>> b
FactSet([
    dice(n=6),
    dice(n=5),
    dice(n=4),
])
>>> a, b = dice.n + dice.n == 13  # no result should probably raise a more specific exception?
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: need more than 0 values to unpack
>>> ab = dice.n + dice.n == 13  # this is much more awkward and forces you to deal with the error in-situ (which might not be what you wanted)
>>> if ab:
>>>     a, b = ab
dice=FactSet() >>>对于范围(1,7)内的i: ... 骰子。加('dice',n=i) ... >>>打印骰子。n+dice.n==10#给我所有加起来等于10的组合 XPROD((骰子(n=4),骰子(n=6)) (骰子(n=5),骰子(n=5)) (掷骰子(n=6),掷骰子(n=4))) >>>a,b=dice.n+dice.n==10#与上述相同,但打开单个模具的包装 >>>a 事实集([ 骰子(n=4), 骰子(n=5), 骰子(n=6), ]) >>>b 事实集([ 骰子(n=6), 骰子(n=5), 骰子(n=4), ]) >>>a,b=dice.n+dice.n==13#没有结果可能会引发更具体的异常? 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 ValueError:需要0个以上的值才能解包 >>>ab=dice.n+dice.n==13#这会更加尴尬,迫使您就地处理错误(这可能不是您想要的) >>>如果ab: >>>a,b=ab 而不是执行以下操作:

a, b = <expression>
正如您所看到的,元组(或者在一般情况下是iterable)只是被迭代。它不知道发生了什么


正如您通过阅读所看到的,这些异常是硬编码的,不能被“覆盖”。

根据@AndreaCorbellini的回答,这里是一个具有合理/可调整语义的自定义迭代器实现:

import collections


class MyTupleIter(collections.Iterator):
    def __init__(self, mt, length):
        self.mt = mt
        self.pos = -1
        self.length = length

    def next(self):
        self.pos += 1
        if self.pos < self.length:
            if self.pos >= len(self.mt):
                return 'empty-value'
            return self.mt[self.pos]
        raise StopIteration


class MyTuple(tuple):
    def __new__(cls, columns=()):
        return tuple.__new__(cls, tuple(columns))

    def __iter__(self):
        return MyTupleIter(self, length=2)


a, b = MyTuple()
print a, b    # empty-value empty-value

a, b = MyTuple(columns=(1,2,3))
print a, b    # 1 2
导入集合
类MyTupleItem(collections.Iterator):
定义初始(自我、mt、长度):
self.mt=mt
self.pos=-1
self.length=长度
def next(自我):
self.pos+=1
如果self.pos=len(self.mt):
返回“空值”
返回self.mt[self.pos]
提出停止迭代
类MyTuple(元组):
定义(cls,列=()):
返回元组。\uuuu新的\uuuu(cls,元组(列))
定义(自我):
返回mytupleter(self,长度=2)
a、 b=MyTuple()
打印a、b#空值空值
a、 b=MyTuple(列=(1,2,3))
打印a,b#1 2

捕获的
值太多而无法解包通常是不良设计的标志。如果你不知道要拆多少东西,最好不要拆。你打算怎么办?“在这里处理解包错误…”的真正含义是什么?唯一合理的方法是将结果放在一个变量中,检查iterable的长度并协调一致。通常对于常规元组可能是这样,但是,对于在容器上实现操作的模块,也就是说:
a,b=(a.date-b.date)
将返回
a
b
中的项目,以便它们的日期字段之间的差异小于2天,或者如果无法满足约束条件,则不会返回任何内容。如果存在需要解包数量可变的参数的用例,则应该从上下文中清除,您可能应该调用一个方法或传递一个特定于这些方法的参数cases@eqzx参数的使用纯粹是为了保持示例的简单,请阅读我对实际用例的其他注释。请注意,问题是关于覆盖tuple unpacking正在从tuple子类中引发的异常tuple。不是关于如何编写异常处理机制。这是否意味着我可以通过编写自己的
集合来完成我想做的事情。迭代器
子类?@thebjorn:mh。。。是和否。您需要提前知道要解包的值的数量(例如,您不能同时编写
a,b=mytuple
a,b,c=mytuple
),并且您的tuple子类将不会按预期的方式运行(例如
list(mytuple)
将抛出奇怪的异常)。@thebjorn:阅读您的用例,我相信你在增加混乱和不确定性。一个有经验的Python开发人员看到像
a,b=dice.n+dice.n==13这样的语句引发您的自定义异常会非常惊讶。您可能是正确的,但是,在项目集合上以声明方式工作(而不是强制迭代)的概念它非常强大,可以为某些问题提供相当优雅的解决方案。不过,获得正确的细节是关键(我从1.4版开始就在使用Python,所以我希望我对如何在Python中实现DSL有一些感觉)。FWIW,您不需要显式地从
迭代器继承(迭代器只是一个实现
\uuuuuuuuu next\uuuuuuu
)的对象。此外,您还可以使用
yield
关键字将
MyTuple.\uuuuuu iter\uuuuuu
实现为生成器。这将导致更简单的实现。
value = <expression>
try:
    a, b = value
except ValueError:
    ...
it = iter(something)

try:
    a = next(it)
    b = next(it)
    ...
    z = next(it)
except StopIteration:
    raise ValueError('need more than X values to unpack')

try:
    next(it)
except StopIteration:
    pass
else:
    raise ValueError('too many values to unpack (expected Y)')
import collections


class MyTupleIter(collections.Iterator):
    def __init__(self, mt, length):
        self.mt = mt
        self.pos = -1
        self.length = length

    def next(self):
        self.pos += 1
        if self.pos < self.length:
            if self.pos >= len(self.mt):
                return 'empty-value'
            return self.mt[self.pos]
        raise StopIteration


class MyTuple(tuple):
    def __new__(cls, columns=()):
        return tuple.__new__(cls, tuple(columns))

    def __iter__(self):
        return MyTupleIter(self, length=2)


a, b = MyTuple()
print a, b    # empty-value empty-value

a, b = MyTuple(columns=(1,2,3))
print a, b    # 1 2