言語を問わず、メソッドの引数にデフォルト値を設定しておく「デフォルト引数」はよく使います。
しかしPythonでは、デフォルト引数の定義タイミングはRubyなど他の言語とは異なっており、ハマりポイントとなっています。
このエントリでは、Python特有のデフォルト引数の定義タイミングを紹介します。
例として、次のようにnumbers
というインスタンス変数を持つ適当なクラスを定義します。
引数numbers
のデフォルト値は空のリスト[]
です。
>>> class Hoge:
... def __init__(self, numbers=[]):
... self.numbers = numbers
...
次に2つのインスタンスを作成し、一方のnumbers
には1
を追加します。
>>> hoge1 = Hoge()
>>> hoge2 = Hoge()
>>>
>>> hoge1.numbers.append(1)
>>> hoge1.numbers
[1]
このとき、もう一方のインスタンスのnumbers
はどうなるでしょうか?
>>> hoge2.numbers
# どうなるでしょう?
答えはhoge1.numbers
と同じ[1]
になります。
>>> hoge2.numbers
[1]
オブジェクトIDを見るとその理由がわかります。
>>> id(hoge1.numbers)
4556099720
>>> id(hoge2.numbers)
4556099720
つまり、引数のデフォルト値(今回のケースでは[]
)は、呼び出し毎に生成されるのではなく、デフォルト引数の定義時に一度だけ生成されていると考えることができます。
呼び出し毎に異なるオブジェクトをデフォルト値として与えたい場合は次のようにします。
>>> class Hoge:
... def __init__(self, numbers=None):
... self.numbers = numbers
... if numbers is None:
... self.numbers = []
...
Rubyでは、デフォルト引数は呼び出し毎に定義されます。
[1] pry(main)> class Hoge
[1] pry(main)* attr_accessor :numbers
[1] pry(main)*
[1] pry(main)* def initialize(numbers: [])
[1] pry(main)* self.numbers = numbers
[1] pry(main)* end
[1] pry(main)* end
[2] pry(main)>
[3] pry(main)> hoge1 = Hoge.new
[4] pry(main)> hoge2 = Hoge.new
[7] pry(main)>
[8] pry(main)> hoge1.numbers.push(1)
=> [1]
[9] pry(main)> hoge1.numbers
=> [1]
[10] pry(main)> hoge2.numbers
=> []
こちらの方が直感的だと思うのは私だけでしょうか...?
以上です。
このエントリでは、Python特有のデフォルト引数の定義タイミングを紹介しました。
コメントを送る
コメントはブログオーナーのみ閲覧できます