2016-05-31 55 views
8

Capisco le differenze tra oggetti mutevoli e immutabili in Python. Ho letto molti post che parlano delle differenze. Tuttavia, non ho letto nulla riguardo a PERCHÉ gli integer sono oggetti immutabili.Perché gli interi sono immutabili in Python?

Esiste un motivo? O è la risposta "è così com'è"?

Modifica: Mi viene richiesto di 'differenziare' questa domanda da altre domande in quanto sembra essere una domanda precedente. Tuttavia, credo che quello che sto chiedendo sia più una questione filosofica di Python piuttosto che una questione tecnica di Python.

Sembra che gli oggetti "primitivi" in Python (cioè stringhe, booleani, numeri, ecc.) Siano immutabili. Ho anche notato che i tipi di dati derivati ​​che sono costituiti da primitive (vale a dire dts, liste, classi) sono mutabili.

È il punto in cui viene tracciata la linea indipendentemente dal fatto che un oggetto sia mutabile o meno? Primitivo vs derivato?

+11

Che cosa esattamente circa un intero vorresti mormorare? I bit? –

+0

Supponendo l'immutabilità di alcuni tipi consente tutti i tipi di ottimizzazioni. Queste ottimizzazioni sono _most_ pronunciate per 'str', ma entrano in gioco per' int', 'float',' tuple', 'frozenset' anche ... Alcuni probabilmente sostengono che l'immutabilità rende il codice più facile da leggere in molti anche le situazioni. Accoppia questo con il fatto che non esiste un modo naturale per mutare interi (diversi da '+ =', '* =', ... che sono abbastanza rari ...) e non sembra essere un buon motivo per non avere immutabili ints. – mgilson

+0

Se è possibile modificare il valore '1' in' '2' e il valore' 2' in '' 1', '2 + 2 == 1' sarebbe' true'; è davvero quello che vuoi? –

risposta

10

Rendere gli interi mutabili sarebbe molto controintuitivo al modo in cui siamo abituati a lavorare con loro.

Considerate questo frammento di codice:

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

Dopo queste assegnazioni sono eseguite prevediamo un avere il valore 1 e b avere il valore 3. L'operazione di aggiunta sta creando un nuovo valore intero dal intero memorizzato in un e un'istanza del numero intero 2. Se l'operazione di addizione appena preso il numero intero a un e proprio mutato poi sia un e b avrebbe il valore 3.

Quindi ci aspettiamo che le operazioni aritmetiche creino nuovi valori per i loro risultati - non per mutare i loro parametri di input.

Tuttavia, ci sono casi in cui la mutazione di una struttura dati è più comoda e più efficiente. Supponiamo per il momento che list.append(x) non abbia modificato list ma abbia restituito una nuova copia di list con x aggiunto. Poi una funzione come questa:

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

sarebbe solo restituire la lista vuota. (Ricordate - qui nums.append(x) non altera nums - restituisce una nuova lista con x allegata Ma questa nuova lista non viene salvato da nessuna parte..)

avremmo scrivere il foo di routine in questo modo:

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

(Questo, infatti, è molto simile alla situazione con le stringhe Python fino a circa 2,6 o forse 2.5.)

Inoltre, ogni volta che ci assegniamo nums = nums.append(x) saremmo Copia di un elenco che è in aumento in termini di dimensioni risultante nel comportamento quadratico. Per questi motivi vengono creati gli oggetti mutabili.

Una conseguenza di fare liste mutabile è che dopo queste dichiarazioni:

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

lista b è cambiato a [1,2,3,4]. Questo è qualcosa con cui viviamo anche se di tanto in tanto ci fa incazzare.

+1

Non penso che l'affermazione "Rendere mutabili gli interi sarebbe molto controintuente al modo in cui siamo abituati a lavorare con loro." 'È necessariamente vero. Ci sono molti altri linguaggi che hanno numeri mutabili ('C' è un esempio molto comune ...). Solo perché siamo abituati agli interi python che sono immutabili * now * non significa che siamo stati utilizzati per interi immutabili quando è stata presa la decisione originale. – mgilson

+1

Il fatto che 'a + = 2' crei un nuovo numero intero è controintuitivo per me. La maggior parte delle volte però, non fa davvero la differenza. Un post chiave che viene in mente è [questo] (https://stackoverflow.com/questions/306313/is-operator-behaves-unexpectedly-with-integers), che è solo un'altra stranezza sul fatto che "nuovo "I numeri interi non vengono sempre creati –

+0

@mgilson - Considereresti i valori di' int' mutabili in C? Certamente gli oggetti bigint 'gmp' sono mutabili, ma non vedo C' ints' essere mutabile allo stesso modo. In definitiva, penso che troveremmo la possibilità di rendere mutabili gli interi in Python, causando più problemi di quanti ne risolverebbe. Quello che vogliamo veramente fare è rendere i nostri compilatori/run-time più intelligenti in modo che possano rilevare quando usano la mutazione invece di creare un nuovo oggetto. Questo ci darà l'efficienza dei valori mutabili con la sicurezza dei valori immutabili. – ErikR

2

Quali sono le decisioni di progettazione per rendere immutabili i numeri in Python?

Ci sono diversi motivi per l'immutabilità, vediamo prima quali sono le ragioni dell'immutabilità?

1- memoria

  • risparmiare memoria. Se è noto che un oggetto è immutabile, può essere facilmente copiato creando un nuovo riferimento allo stesso oggetto.
  • Prestazioni. Python può allocare spazio per un oggetto immutabile al momento della creazione e i requisiti di archiviazione sono fissi e immutabili.

2- Esecuzione veloce.

  • Non è necessario copiare ogni parte dell'oggetto, solo un semplice riferimento.
  • Facile da confrontare, confrontare l'uguaglianza per riferimento è più veloce rispetto al confronto dei valori.

3- sicurezza:

  • In applicazioni Multi-filettare Diversi fili possono interagire con i dati contenuti all'interno degli oggetti immutabili, senza preoccuparsi coerenza dei dati.
  • Lo stato interno del programma sarà coerente anche se si dispone di eccezioni.
  • classi dovrebbero essere immutabili a meno che non ci sia una buona ragione per farli mutevole .... Se una classe non può essere fatto immutabile, limitare la sua mutevolezza, per quanto possibile

4- Facilità di utilizzare

  • È più facile da leggere, più facile da gestire e meno probabilità di fallire in modi strani e imprevedibili.
  • Gli oggetti immutabili sono più facili da testare, non solo per la loro facile presa in giro, ma anche per gli schemi di codice che tendono ad applicare.

5- Keys must be immutable. Il che significa che è possibile utilizzare stringhe, numeri o tuple come chiave del dizionario. Questo è qualcosa che vuoi usare.

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. 

Tornando ai numeri interi:

  • Security(), facile da usare() e la capacità di usare i numeri come chiavi nei dizionari () sono le ragioni per cui è stata presa la decisione di rendere i numeri immutabili.

  • Ha requisiti di memoria fissi dal momento della creazione().

  • Tutto in Python è un oggetto, i numeri (come le stringhe) sono oggetti "elementali". Nessuna quantità di attività cambierà il valore 8 in qualcos'altro, e nessuna quantità di attività cambierà la stringa "otto" in qualcos'altro. Questo perché anche un decision in the design.