web-dev-qa-db-ja.com

Pythonで整数が不変なのはなぜですか?

Pythonの可変オブジェクトと不変オブジェクトの違いを理解しています。私は違いを議論する多くの投稿を読みました。ただし、整数が不変オブジェクトである理由については何も読んでいません。

これには理由がありますか?それとも「それがまさにそれだ」という答えですか?

編集:以前に尋ねられた質問のように思われるため、他の質問からこの質問を「区別する」ように求められます。ただし、私が求めているのは、技術的なPythonの質問ではなく、哲学的なPythonの質問です。

Python(つまり、文字列、ブール値、数値など)の「プリミティブ」オブジェクトは不変であるように見えます。また、プリミティブで構成される派生データ型(つまり、dicts)にも気づきました、リスト、クラス)は変更可能です。

オブジェクトが変更可能かどうかに関係なく、線が描画される場所はどこですか?プリミティブvs派生?

20
Izzo

整数を変更可能にすることは、整数の操作に慣れ親しんでいる方法とは非常に直観に反します。

次のコードを検討してください。

_a = 1       # assign 1 to a
b = a+2     # assign 3 to b, leave a at 1
_

これらの割り当てが実行された後、aの値は1になり、bの値は3になるはずです。加算演算では、-に格納された整数から新しい整数値が作成されますaと整数のインスタンス2.加算演算がaで整数を取得し、それを単に変更した場合、両方のabの値は3です。

そのため、算術演算では、結果の新しい値を作成することを期待します-入力パラメーターを変更することはありません。

ただし、データ構造を変更する方が便利で効率的な場合があります。今のところ、list.append(x)listを変更せず、listxを追加した新しいコピーを返したとしましょう。次に、このような関数:

_def foo():
  nums = []
  for x in range(0,10):
    nums.append(x)
  return nums
_

空のリストを返すだけです。 (-ここでnums.append(x)numsを変更しません-xが追加された新しいリストを返します。ただし、この新しいリストはどこにも保存されません。)

fooルーチンを次のように記述する必要があります。

_def foo():
  nums = []
  for x in range(0,10):
    nums = nums.append(x)
  return nums
_

(実際、これはPython約2.6またはおそらく2.5までの文字列)の状況と非常に似ています。

さらに、nums = nums.append(x)を割り当てるたびに、サイズが増加するリストをコピーし、結果として2次の動作になります。これらの理由により、リストmutableオブジェクトを作成します。

リストを変更可能にすることの結果は、これらのステートメントの後です:

_a = [1,2,3]
b = a
a.append(4)
_

リストbは_[1,2,3,4]_に変更されました。時々つまづきますが、これは私たちが一緒に住んでいるものです。

16
ErikR

Pythonで数値を不変にするための設計上の決定は何ですか?

不変性にはいくつかの理由があります。最初に見てみましょう不変性の理由は何ですか?

1-メモリ

  • メモリを節約します。オブジェクトが不変であることはよく知られている場合、簡単にコピーして、同じオブジェクトへの新しい参照を作成できます。
  • パフォーマンス。 Pythonは、作成時に不変オブジェクトにスペースを割り当てることができ、ストレージ要件は固定されており、不変です。

2-高速実行

  • オブジェクトの各部分をコピーする必要はなく、単純な参照のみです。
  • 比較が容易で、参照による同等性の比較は値の比較よりも高速です。

3-セキュリティ

  • マルチスレッドアプリでは、データの一貫性を気にすることなく、さまざまなスレッドが不変オブジェクト内に含まれるデータと対話できます。
  • 例外があっても、プログラムの内部状態は一貫しています。
  • クラスを変更可能にする十分な理由がない限り、クラスは不変である必要があります...クラスを不変にすることができない場合は、その変更可能性を可能な限り制限してください

4-使いやすさ

  • 読みやすく、保守が容易で、奇妙で予測できない方法で失敗する可能性が低くなります。
  • 不変オブジェクトは、モック化が容易であるだけでなく、強制する傾向のあるコードパターンにより、テストが容易です。

5-キーは不変でなければならない。つまり、文字列、numbers、またはタプルを辞書のキーとして使用できます。これはあなたが使いたいものです。

The hash table implementation of dictionaries uses a hash value calculated from the key value to find the key. If the key were a mutable object, its value could change, and thus its hash could also change. But since whoever changes the key object can’t tell that it was being used as a dictionary key, it can’t move the entry around in the dictionary. Then, when you try to look up the same object in the dictionary it won’t be found because its hash value is different. If you tried to look up the old value it wouldn’t be found either, because the value of the object found in that hash bin would be different.

整数に戻る:

  • セキュリティ(3)、使いやすい(4)および容量辞書でキーとして数値を使用すること(5)は、数値を不変にすることを決定する理由です。

  • 作成時からのメモリ要件は固定されています(1)。

  • すべてのPythonはオブジェクトであり、numbers(文字列のような)は「基本的な」オブジェクトです。アクティビティの量はありませんこれは、値8を他の値に変更し、アクティビティの量によって文字列「8」が他の値に変更されることはありません。これは、 設計の決定 も原因です。

6
Facundo Victor