ProgrammingPythonバックエンド開発者

Pythonにおけるオブジェクトのミュータブル(mutable)/ イミュータブル(immutable)とは何ですか?これが関数の動作や引数の渡し方にどのように影響しますか?典型的なエラーの例を挙げてください。

Hintsage AIアシスタントで面接を突破

答え。

ミュータブルとは、オブジェクトの識別子(メモリアドレス)を変更せずにオブジェクトを変更できるかどうかを定義します:

  • ミュータブルオブジェクト(例:list, dict, set)は変更可能であり、要素を追加したり、変更したり、削除したりできます。
  • イミュータブルオブジェクト(例:int, str, tuple, frozenset)は一度作成された後に変更できず、あらゆる「変更」は新しいオブジェクトを生成します。

関数への影響:

  • ミュータブルオブジェクトを関数に渡すと、その関数はそれを変更できます。
  • イミュータブルオブジェクトは、関数内で「置き換え」られても変更は行われません。

例:

def f(lst): lst.append(42) data = [] f(data) print(data) # [42] def f2(x): x += 1 n = 1 f2(n) print(n) # 1

器用に仕掛けられた質問。

「次のコードは何を出力しますか?」

def foo(bar=[]): bar.append(1) return bar print(foo()) print(foo())

答え: 出力は:

[1]
[1, 1]

関数の引数は定義時に一度だけ初期化され、各呼び出しごとではありません。リスト(および他のミュータブルオブジェクト)は、関数の引数における一般的な落とし穴です。

このテーマの微妙な点を知らないことによる実際のエラーの例。


物語

REST APIがデフォルト引数を持つ関数を介してリストを返していました:

def get_default_items(items=[]): items.append('x') return items

数回の呼び出しの後、リストが増えていることに気付き、1つの要素しか得られないと期待していました。


物語

関数内で文字列を「置き換える」予定でした:

def replace_word(word): word.replace('a', 'b') word = 'data' replace_word(word) print(word) # 'dbtb' を予想して 'data' を得た

strメソッドは元の文字列を変更せず、新しいものを返しますが、その返り値を無視しました。


物語

ネストされた構造で作業している際に:

original = [[1, 2], [3, 4]] copy = original[:] copy[0][0] = -1 print(original) # [[-1, 2], [3, 4]]

浅いコピーを使用し、コピーのみを変更したと考えていましたが、ネストされたオブジェクトは共有されていました。