Python Language
リスト構造解除(パッキングとアンパックともいう)
サーチ…
デストラクションの割り当て
代入では、 "unpacking"構文を使用してIterableを値に分割できます。
値としての破壊
a, b = (1, 2)
print(a)
# Prints: 1
print(b)
# Prints: 2
iterableの長さを超えて解凍しようとすると、エラーが発生します:
a, b, c = [1]
# Raises: ValueError: not enough values to unpack (expected 3, got 1)
リストとしての破壊
次の構文を使用して、未知の長さのリストをアンパックすることができます。
head, *tail = [1, 2, 3, 4, 5]
ここでは、最初の値をスカラーとして抽出し、他の値をリストとして抽出します。
print(head)
# Prints: 1
print(tail)
# Prints: [2, 3, 4, 5]
これは次のものと同等です:
l = [1, 2, 3, 4, 5]
head = l[0]
tail = l[1:]
また、複数の要素または要素がリストの最後を形成して動作します。
a, b, *other, z = [1, 2, 3, 4, 5]
print(a, b, z, other)
# Prints: 1 2 5 [3, 4]
割り当てを破棄する際の値を無視する
特定の値だけに興味がある場合は、 _
を使用して興味のないことを示すことができます。注:これはまだ設定されています_
、ほとんどの人は変数として使用しません。
a, _ = [1, 2]
print(a)
# Prints: 1
a, _, c = (1, 2, 3)
print(a)
# Prints: 1
print(c)
# Prints: 3
割り当てを破棄する際にリストを無視する
最後に、代入で*_
構文を使用して多くの値を無視できます。
a, *_ = [1, 2, 3, 4, 5]
print(a)
# Prints: 1
これは本当に興味深いものではありません。リスト上でインデックスを使用することができます。最初の値と最後の値を1つの割り当てで保持するのがうまくいけば:
a, *_, b = [1, 2, 3, 4, 5]
print(a, b)
# Prints: 1 5
一度に複数の値を抽出することもできます。
a, _, b, _, c, *_ = [1, 2, 3, 4, 5, 6]
print(a, b, c)
# Prints: 1 3 5
パッキング関数の引数
関数では、いくつかの必須引数を定義できます。
def fun1(arg1, arg2, arg3):
return (arg1,arg2,arg3)
3つの引数が与えられた場合にのみ関数を呼び出し可能にします:
fun1(1, 2, 3)
デフォルト値を使用して、引数をオプションとして定義できます。
def fun2(arg1='a', arg2='b', arg3='c'):
return (arg1,arg2,arg3)
次のようなさまざまな方法で関数を呼び出すことができます:
fun2(1) → (1,b,c)
fun2(1, 2) → (1,2,c)
fun2(arg2=2, arg3=3) → (a,2,3)
...
しかし、構造化構文を使用して引数をパックすることもできるので、 list
やdict
を使って変数を割り当てることができます。
引数リストのパッキング
あなたは値のリストを持っていると考えてください
l = [1,2,3]
*
構文を使用して、値のリストを引数として関数を呼び出すことができます。
fun1(*l)
# Returns: (1,2,3)
fun1(*['w', 't', 'f'])
# Returns: ('w','t','f')
しかし、あなたが引数の数に一致する長さのリストを提供しないならば:
fun1(*['oops'])
# Raises: TypeError: fun1() missing 2 required positional arguments: 'arg2' and 'arg3'
パッキングキーワードの引数
今では、辞書を使って引数をパックすることもできます。 **
演算子を使用すると、 dict
をパラメータ値として展開するようにPythonに指示できます。
d = {
'arg1': 1,
'arg2': 2,
'arg3': 3
}
fun1(**d)
# Returns: (1, 2, 3)
関数が位置引数(デフォルト値を持たない引数)しか持っていないときは、予想されるすべてのパラメータを含むように辞書を必要とし、余分なパラメータを持たないか、エラーが発生します:
fun1(**{'arg1':1, 'arg2':2})
# Raises: TypeError: fun1() missing 1 required positional argument: 'arg3'
fun1(**{'arg1':1, 'arg2':2, 'arg3':3, 'arg4':4})
# Raises: TypeError: fun1() got an unexpected keyword argument 'arg4'
オプションの引数を持つ関数の場合、同じ方法で引数を辞書としてパックできます。
fun2(**d)
# Returns: (1, 2, 3)
しかし、デフォルト値に置き換えられるので、値を省略することができます:
fun2(**{'arg2': 2})
# Returns: ('a', 2, 'c')
以前と同じように、既存のパラメータではない追加の値を与えることはできません。
fun2(**{'arg1':1, 'arg2':2, 'arg3':3, 'arg4':4})
# Raises: TypeError: fun2() got an unexpected keyword argument 'arg4'
実際の使用法では、関数は位置とオプションの両方の引数を持つことができ、同じ働きをします:
def fun3(arg1, arg2='b', arg3='c')
return (arg1, arg2, arg3)
iterableだけで関数を呼び出すことができます:
fun3(*[1])
# Returns: (1, 'b', 'c')
fun3(*[1,2,3])
# Returns: (1, 2, 3)
またはちょうど辞書で:
fun3(**{'arg1':1})
# Returns: (1, 'b', 'c')
fun3(**{'arg1':1, 'arg2':2, 'arg3':3})
# Returns: (1, 2, 3)
同じ呼び出しで両方を使用することもできます。
fun3(*[1,2], **{'arg3':3})
# Returns: (1,2,3)
ただし、同じ引数に対して複数の値を指定することはできません。
fun3(*[1,2], **{'arg2':42, 'arg3':3})
# Raises: TypeError: fun3() got multiple values for argument 'arg2'
関数の引数を展開する
任意の数の引数を受け入れることができる関数を作成し、 "コンパイル"時に引数の位置や名前を強制しない場合は、次のようにします。
def fun1(*args, **kwargs):
print(args, kwargs)
*args
パラメータと**kwargs
パラメータは、 tuple
とdict
にそれぞれ設定された特別なパラメータです。
fun1(1,2,3)
# Prints: (1, 2, 3) {}
fun1(a=1, b=2, c=3)
# Prints: () {'a': 1, 'b': 2, 'c': 3}
fun1('x', 'y', 'z', a=1, b=2, c=3)
# Prints: ('x', 'y', 'z') {'a': 1, 'b': 2, 'c': 3}
十分なPythonコードを見ると、引数を別の関数に渡すときに広く使用されていることがすぐわかります。たとえば、文字列クラスを拡張する場合は次のようにします。
class MyString(str):
def __init__(self, *args, **kwarg):
print('Constructing MyString')
super(MyString, self).__init__(*args, **kwarg)