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

アンパックを使用して 3 つの異なる変数に割り当てています。そうするために、アンパック右側のシーケンスを反復する必要があります。

ジェネレータ式は文字列との2 つのUNPACK_SEQUENCE値しか生成しないため、 は実際に例外をスローしていますが、左側の名前リストには3 つの名前があります。'1''2'

これはジェネレータの問題ではありません。これはタプル代入の制限であり、明示的に文書化されています:

  • ターゲット リストがターゲットのコンマ区切りリストの場合: オブジェクトは、ターゲット リスト内のターゲットと同じ数のアイテムを持つ iterable である必要があり、アイテムは左から右に対応するターゲットに割り当てられます。

リストを使用すると、同じエラーがスローされます。

a, b, c = list(x)

x長さが 3 でない限り、同じ例外をスローします。x = '123'

ジェネレーター式を1 つの変数に自由に割り当てることができます。

>>> 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 に答える