pythonにおけるグローバル変数

 pythonグローバル変数は引っかかりやすいねという話です。ほとんど自分のメモ用です。
 C++などではグローバル変数は名前の衝突が怖いとだけ思っておけばいい*1のですが、pythonではそうではありません。グローバルに宣言した変数は基本的には関数内で書き換えることが不可能で、書き換えるためには関数内でglobalを宣言しなければいけません。もしglobal宣言をしないで値を代入したらそれはローカル変数とみなされます。つまり、以下のようなことです

a = 1
def change():
    a = 0
    return

def change2():
    global a
    a = 0
    return

print a # -> 1
change()
print a # -> 1
change2()
print a # -> 0

 しかし、実はリストや辞書の場合は少し違って、globalを宣言しなくても値が代入できてしまいます。

a = [1, 2, 3]
def change():
    a[0] = 0
    return

print a # -> [1, 2, 3]
change()
print a # -> [0, 2, 3]

 僕はpythonに疎いですし、あまりこのことに関する文献も見つからなかったのでどうしてこうなってるのかはよくわかりませんし、どのようなときにglobalを宣言しなくてもいいのかもわかっていませんが、immutableかどうかで分かれているんじゃないかなと予想しています。関数の引数の時の話と似ていますからね。
 しかし、そもそもglobalな変数を書き換えるなんて基本的にやってはいけないので気を付けましょう*2

追記

 マサカリを飛ばしてもらいました。listの書き換えは変数を生成するのではなく、listにアクセスしてからオブジェクトを変更しているだけなので問題ないということでした。

*1:マサカリが飛んできそう

*2:自戒です