関数のデフォルト引数を舐めて破壊的な事をするとエラいことになる罠

@aodag 先生に教えてもらった、Python童貞がはまるだろう罠。

pythonのデフォルト引数に破壊的な操作をすると、想像しなかった挙動なるのでメモメモ。

#!/usr/bin/env python
#-*- coding:utf8 -*-

def bucho_make_love(name, lovers=[]):
    lovers.append(name)
    return lovers

print bucho_make_love('haru')  #=> ['haru']
print bucho_make_love('ae35') #=> ['haru', 'ae35']
print bucho_make_love('shin')  #=> ['haru', 'ae35', 'shin']

デフォル引数「lovers」はリストなんだけど、そのリストにappendしていくと、どんどんloversに追加されていってしまうw

デフォルト引数に可変性のオブジェクトを使う時には気をつけましょう。勉強になりました。

なんでそうなるのか、ろくに調べもしないで想像したことを書いてみると、Pythonの世界では変数はすべてオブジェクトに対するリファレンスであるという事が関係しているような気がします。

なのでデフォルト引数は関数の実行時に毎回変数に新しいオブジェクトのリファレンスを突っ込むんじゃなくて、「引数がなかったら、この変数(lovers)は、このオブジェクト(リスト)に対するリファレンスを持つよ。このオブジェクトの初期値は[ ]だよ」という風な事を意味しているのだと理解した。

完全に眠気にまかして書いたので間違ってたらごめんなさい。