Python で多重代入を利用した変数の swap
Python の 6.3 代入文 (assignment statement) によると、
代入の定義では、左辺値と右辺値がオーバラップするような代入 (例えば、"a, b = b, a" を行うと、二つの変数を入れ替えます) を定義しても `安全 (safe)' に代入できます …
例えば、2 つの変数 a, b を入れ替えるなら、変数の値を退避しておく一時変数を省略できる。
a = "hoge" b = "piyo" a, b = b, a print a,b #=> piyo hoge
代入対象の変数にオーバーラップがある場合
注意点としては、
代入対象となる変数群 の間で オーバラップがある場合は安全ではありません!
(同上より)
次のようなケース。
ary = ["hoge", "piyo", "fuga"] i = 100 i, ary[i] = 1, 999 print ary #=> ['hoge', 999, 'fuga']
もし、swap が見かけ通り一つの文として同時に実行されているなら、swap を行う時点の i の値は 100 となり、ary[100] は存在しないためにエラーとなる。しかし、実際には最初の i に 1 が代入されたことにより、i の値が上書きされ、ary[1] に 999 が代入される。
以下のように順次実行されているのと同じように見える。
i= 1 ary[i] = 999
しかし、変数を a, b を swap したときのように swap させると、
ary = [1,2,3,4,5] i = 0 i, ary[i] = ary[i], i print i, ary
結果は、
1 [1, 0, 3, 4, 5]
となる。 右辺の i は更新される前の i の値を参照しているようで、何だかよくわからなくなってきた。 (+_+)
てっきり、以下のように実行されるのかと思った。
i = ary[i] ary[i] = i
右辺の代入される値は、多重代入の前の変数で名前解決が行われるのかな?
i = ary[0] ary[i] = 0
Ruby で多重代入を利用した変数の swap
同じく多重代入ができる Ruby で動作を確認すると、
a = "hoge" b = "piyo" a, b = b, a p a,b
次のように同じ結果となる。
"piyo" "hoge"
また、「代入対象となる変数群の間でオーバラップがある場合」も結果は同じ。
ary = ["hoge", "piyo", "fuga"] i = 100 i, ary[i] = 1, 999 p ary #=> ["hoge", 999, "fuga"]
以下も Python と同じ。
ary = [1,2,3,4,5] i = 0 i, ary[i] = ary[i], i p i, ary
結果は、
1 [1, 0, 3, 4, 5]
0コメント:
コメントを投稿