0

考虑以下功能;

def myfunc():
    a=b=c=0
    x='12'
    a,b,c=(i for i in x)
    return a,b,c

此函数抛出以下异常: ValueError:需要超过 2 个值才能解包。我的意图是按给定顺序将“x”变量中的可用值分配给左侧的变量。因此a = 1,b = 2,c = 3,我想做的。

为了提高我对生成器的理解,我对函数进行了反汇编

>>> dis.dis(myfunc)
  2           0 LOAD_CONST               1 (0)
              3 DUP_TOP             
              4 STORE_FAST               0 (a)
              7 DUP_TOP             
              8 STORE_FAST               1 (b)
             11 STORE_FAST               2 (c)

  3          14 LOAD_CONST               2 ('12')
             17 STORE_FAST               3 (x)

  4          20 LOAD_CONST               3 (<code object <genexpr> at 0x297b430, file "<stdin>", line 4>)
             23 MAKE_FUNCTION            0
             26 LOAD_FAST                3 (x)
             29 GET_ITER            
             30 CALL_FUNCTION            1
             33 UNPACK_SEQUENCE          3
             36 STORE_FAST               0 (a)
             39 STORE_FAST               1 (b)
             42 STORE_FAST               2 (c)

  5          45 LOAD_FAST                0 (a)
             48 LOAD_FAST                1 (b)
             51 LOAD_FAST                2 (c)
             54 BUILD_TUPLE              3
             57 RETURN_VALUE   

我猜是 UNPACK_SEQUENCE 正在引发异常。是否可以在 UNPACK_SEQUENCE 之前执行 STORE_FAST?希望我的问题是有道理的。

4

1 回答 1

2

您正在使用解包分配三个不同的变量。为了做到这一点,解包必须遍历右手序列。

UNPACK_SEQUENCE确实抛出了异常,因为您的生成器表达式仅产生两个,即字符串'1''2',但您的左侧名称列表有3 个名称。

这不是发电机的问题。这是元组分配的限制,明确记录

  • 如果目标列表是逗号分隔的目标列表:该对象必须是与目标列表中的目标具有相同数量的项目的可迭代对象,并且项目从左到右分配给相应的目标。

使用列表时会抛出相同的错误:

a, b, c = list(x)

抛出相同的异常,除非x长度为 3,例如x = '123'

您可以自由地将生成器表达式分配给一个变量:

>>> x = '12'
>>> a = (i for i in x)
>>> a
<generator object <genexpr> at 0x105046dc0>

如果您希望c保持设置为,0因为生成器没有提供足够的值,那么这不是元组分配的工作方式。

您可以使用具有默认值的辅助函数:

def helper(a=0, b=0, c=0):
    return a, b, c

a, b, c = helper(*(i for i in x))

演示:

>>> def helper(a=0, b=0, c=0):
...     return a, b, c
... 
>>> a, b, c = helper(*(i for i in x))
>>> a, b, c
('1', '2', 0)

辅助函数对所有参数使用默认值,*调用语法使用生成器将它们视为位置参数。

于 2013-05-08T10:35:31.177 回答