2016-05-31 27 views
8

我瞭解Python中可變對象和不可變對象的區別。我已經閱讀了很多文章,討論這些差異。但是,我還沒有讀到任何有關爲什麼整數是不可變的對象。爲什麼整數在Python中是不可變的?

是否存在這樣的原因?或者答案是「這是怎麼回事」?

編輯:我得到提示將這個問題與其他問題區分開來,因爲它似乎是以前提出的問題。然而,我相信我所要求的更多是哲學上的Python問題,而不是技術性的Python問題。

似乎Python中的「原始」對象(即字符串,布爾值,數字等)是不可變的。我還注意到,由基元組成的派生數據類型(即字典,列表,類)是可變的。

無論對象是否可變,繪製線的位置是?原始與派生?

+11

你想要改變一個整數究竟是什麼?位? –

+0

假設某些類型的不變性可以實現各種優化。這些優化對於'str'來說是_most_發音,但它們也起作用於'int','float','tuple','frozenset' ......有些人可能會認爲不變性使得代碼更易於閱讀情況也一樣。再加上事實上,沒有一種自然的方式來改變整數(除了'+ =','* =',...這是非常罕見的......),而且似乎並不好沒有一成不變的理由。 – mgilson

+0

如果你可以修改值'1'爲'2',值'2'爲'1',那麼'2 + 2 == 1'就是'true';那真的是你想要的嗎? –

回答

10

使整數可變將與我們習慣使用它們的方式非常不直觀。

考慮以下代碼片段:

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

後這些任務執行我們預計一個有值1和b有值3加法運算是創建一個新的整數值從存儲的整數和整數2的一個實例。 如果加法操作只取整數a並且只是突變它然後ab將具有值3.

因此,我們期望算術運算爲其結果創建新值 - 而不是改變它們的輸入參數。

但是,在某些情況下,更改數據結構更方便更高效。假設目前list.append(x)沒有修改list,但返回了list的新副本,並且附加了x。 然後這樣的功能:

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)時間,我們將複製大小爲導致增加的列表在二次行爲。 由於這些原因,我們列出了可變對象對象。

的後果,以使列出可變的是,這些語句後:

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

列表b已更改爲[1,2,3,4]。這是我們生活的東西,儘管它現在仍然讓我們trips trips不安。

+1

我不認爲'使整數可變會使我們習慣於與它們一起工作的方式非常相反。''必然是正確的。還有很多其他語言都有可變的整數('C'是一個很常見的例子......)。僅僅因爲我們已經習慣了python整數是不可變的*現在*並不意味着我們在做出最初的決定時習慣了不變的整數。 – mgilson

+1

「a + = 2」創建一個新的整數對我來說是直觀的。但大多數時候,它確實沒有什麼區別。想到的一個關鍵的帖子是[這一個](https://stackoverflow.com/questions/306313/is-operator-behaves-unexpectedly-with-integers),這是一個更奇怪的事實,「新「整數並不總是創建 –

+0

@mgilson - 你會認爲'int'值在C中是可變的嗎?當然'gmp' bigint對象是可變的,但我沒有看到C'ints'以相同的方式變化。最終,我認爲我們會發現使Python整數可變會導致更多的問題,而不是解決問題。我們真正想要做的是讓我們的編譯器/運行時更加智能,以便他們能夠檢測到他們何時使用突變而不是創建新對象。這將給我們帶來不變價值安全的可變值的效率。 – ErikR

2

什麼是使數字在Python中不可變的設計決策?

不變性有幾個原因,讓我們先看看不變性的原因是什麼?

1- 存儲器

  • 節省存儲器。如果衆所周知的是一個對象是不可變的,那麼它可以很容易地被複制,從而爲同一個對象創建一個新的引用。
  • 表現。 Python可以在創建時爲不可變對象分配空間,並且存儲需求是固定不變的。

2- 快速執行

  • 它不必複製對象的每個部分,只是一個簡單的參考。
  • 易於比較,通過引用比較相等比比較值更快。

3- 安全

  • 在多線程應用程序不同的線程可以與包含在不變的對象內部的數據進行交互,而無需擔心數據的一致性。
  • 即使您有例外,程序的內部狀態也會保持一致。
  • 類應該是一成不變的,除非有一個很好的理由讓他們可變....如果一個類不能進行能不變,限制了它的可變性儘可能

4- 易於使用

  • 易於閱讀,易於維護且不太可能以奇怪和不可預知的方式失敗。
  • 不變對象更容易測試,這不僅因爲它們易於實現的可模仿性,還因爲它們傾向於強制執行的代碼模式。

5- Keys must be immutable。這意味着你可以使用字符串,數字或元組作爲字典鍵。這是你想使用的東西。

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. 

回過頭來看看這個整數:

  • 安全(),使用方便(),並使用數字作爲字典鍵的能力( )是使數字不可變的決定的原因。

  • 自創建時起就有固定內存要求()。

  • Python中的所有對象都是「元素」對象,數字(如字符串)是「元素」對象。沒有任何活動會將價值8改變成其他任何東西,並且沒有任何活動會將字符串「八」改變爲其他任何東西。這是因爲decision in the design也是。

相關問題