Pythonの分配束縛

◆タプルで分配束

x,y にまとめて値を代入するようなコードでは普通に使っていました。

(x,y) = (1,2)
#あるいは
x, y = 1, 2

でも、もっと複雑な構造でも、分配束縛できるのは知らなかった。

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

[a,b,c,d] #=> [1, 2, 3, 4]

これでも出来ますが、

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

不恰好ですね。

◆関数で分配束

これもしらなかったんですが、

data = (1, (2, (3,)), 4)
foo = lambda (a, (b, (c,)), d): [a, b, c, d]

foo(data) #=> [1, 2, 3, 4]

仮引数にタプルを書くことができるんですね。そして代入の時と同じように引数を分配束縛します。
もちろん、普通の関数定義でも出来ます。

def bar((a, (b, (c,)), d)):
    return [a, b, c, d]

bar(data) #=> [1, 2, 3, 4]

◆仮引数がひとつの場合

以下余談。次の3つの lambda 式、違いが分かりますか?

f1 = lambda (x): x
f2 = lambda (x,): x
f3 = lambda x,: x
f1(100)    #=> 100
f2((100,)) #=> 100
f3(100)    #=> 100

f1 の仮引数についているカッコは特に構文的な意味をもっていません。

f1 = lambda x: x
f1 = lambda (x): x
f1 = lambda ((x)): x
f1 = lambda ((((((((((x)))))))))): x

どれも一緒です。

f2 は仮引数がタプルです。 Python では要素数がひとつのタプルは (a,) のようにカンマを付けます。
仮引数がタプルなので実引数もタプルでなければなりません。

f2 = lambda (x,): x

f2(100)    #=> error
f2((100,)) #=> 100

カッコが二重になるのが不自然ですが次のような場合はそうでもない...かもしれません。

x = 100,  #1要素のタプル
f2(x) #=> 100

さて f3 ですが。

f3 = lambda x,: x

一見、仮引数が「1要素のタプル」にみえますが違います。
python では仮引数にも実引数にも、末尾にカンマを余分につけることが許されているのです。
つまり f3 は、単に1引数の関数になります。

f3(100) #=> 100

最後に、実引数に余分なカンマを付ける例も書いてみましょうか。

pow(2,10)  #=> 1024
pow(2,10,) #=> 1024

まー、なんてことはないです。キモイだけです。