2016-01-10 13 views
9

Per quanto ho capito, le tuple e le stringhe sono immutabili per consentire ottimizzazioni come il riutilizzo della memoria che non cambierà. Tuttavia, una ovvia ottimizzazione, facendo sì che sezioni di tuple si riferiscano alla stessa memoria della tupla originale, non è inclusa in Python.Dato che le tuple sono immutabili, perché le affettatrici fanno una copia invece di una vista?

So che questa ottimizzazione non è compreso perché quando ho tempo la seguente funzione, tempo impiegato va come O (n^2) invece di O (n), in modo completo la copia è in corso:

def test(n): 
    tup = tuple(range(n)) 
    for i in xrange(n): 
     tup[0:i] 

C'è qualche comportamento di Python che cambierebbe se questa ottimizzazione fosse implementata? C'è qualche vantaggio in termini di prestazioni nel copiare anche quando l'originale è immutabile?

+8

A volte la risposta è "perché nessuno ha avuto il tempo di implementarlo completamente ancora". –

+1

Invia una richiesta pull :) –

+0

Potrebbe essere un compromesso tra la riduzione della quantità di copiatura, come si fa notare, e la riduzione del numero di conteggi di riferimento alla tupla originale, in modo che possa essere eliminata in precedenza. – cr3

risposta

1

Per view, stai pensando a qualcosa di equivalente a ciò che fa numpy? Ho familiarità con come e perché lo fa numpy.

A numpyarray è un oggetto con informazioni di forma e dtype, oltre a un buffer di dati. È possibile visualizzare queste informazioni nella proprietà __array_interface__. Un view è un nuovo oggetto numpy, con il proprio attributo di forma, ma con un nuovo puntatore del buffer di dati che punta a un posto nel buffer di origine. Ha anche una bandiera che dice "Non possiedo il buffer". numpy mantiene anche il proprio conteggio dei riferimenti, quindi il buffer dei dati non viene distrutto se l'array originale (proprietario) viene eliminato (e la raccolta dei dati inutili).

Questo utilizzo delle viste può essere un grande risparmio di tempo, soprattutto con array molto grandi (le domande sugli errori di memoria sono comuni su SO). Le viste consentono anche differenti dtype, quindi un buffer di dati può essere visualizzato con numeri interi a 4 byte, o 1 byte caratteri, ecc.

Come si applica alle tuple? La mia ipotesi è che richiederebbe molto bagaglio extra. Una tupla consiste in un set fisso di puntatori di oggetti, probabilmente un array C. Una vista userebbe la stessa matrice, ma con i propri indicatori di inizio e fine (puntatori e/o lunghezze). Che ne dici di condividere le bandiere? Raccolta dei rifiuti?

E qual è la dimensione e l'uso tipici delle tuple? Un uso comune delle tuple consiste nel passare argomenti a una funzione. La mia ipotesi è che la maggior parte delle tuple in una tipica esecuzione di Python siano di piccole dimensioni: 0, 1 o 2 elementi. Le fette sono consentite, ma sono molto comuni? Sulle tuple piccole o molto grandi?

Ci sarebbero delle conseguenze non intenzionali nel rendere le viste delle tuple slice (nel senso intorpidito)? La distinzione tra visualizzazioni e copie è una delle cose più difficili da comprendere per gli utenti di numpy. Poiché una tupla dovrebbe essere immutabile, ovvero i puntatori della tupla non possono essere modificati, è possibile che le visualizzazioni di implementazione siano invisibili agli utenti. Ma comunque mi chiedo.

Potrebbe essere più sensato provare questa idea su un ramo della versione PyPy, a meno che non si desideri veramente scavare nel codice Cpython. O come una classe personalizzata con Cython.

Problemi correlati