Domanda

  

metodi dict dict.keys (), dict.items ()   e dict.values ??() restituiscono & # 8220; visualizza & # 8221;   anziché le liste.    http://docs.python.org/dev/3.0/whatsnew//3.0 .html

Innanzitutto, in che modo una vista è diversa da un iteratore? In secondo luogo, qual è il vantaggio di questo cambiamento? È solo per motivi di prestazioni?

Non mi sembra intuitivo, cioè sto chiedendo un elenco di cose (dammi tutte le tue chiavi) e sto recuperando qualcos'altro. Ciò confonderà le persone?

È stato utile?

Soluzione

Stai effettivamente ottenendo un elenco. Non è solo una copia dell'elenco interno, ma qualcosa che si comporta come se fosse un elenco ma rappresenta solo lo stato interno.

È allo stesso modo implementato in Java (e probabilmente anche in molti altri linguaggi / ambienti).

Il motivo principale è che per molti casi d'uso la restituzione di un elenco completamente separato è inutile e dispendiosa. Richiederebbe la copia dell'intero contenuto (che può essere o non essere molto).

Se si desidera semplicemente scorrere le chiavi, non è necessario creare un nuovo elenco. E se davvero ne hai bisogno come elenco separato (come copia), puoi facilmente creare tale elenco dalla vista.

Altri suggerimenti

La risposta di Joachim Sauer spiega molto bene perché non viene restituito un list . Ma questo lascia la domanda sul perché queste funzioni non restituirebbero iteratori, proprio come hanno fatto iteritems ecc. In Python 2.

Un iteratore è molto più restrittivo di un contenitore. Ad esempio, un iteratore non consente più di un passaggio; se provi un secondo passaggio, troverai che è vuoto. Pertanto, operazioni come elem in cont sono supportate da contenitori, ma non possono essere supportate da iteratori: una volta verificato se un elemento è " in " l'iteratore, l'iteratore viene distrutto!

D'altra parte, ottenere un contenitore di solito richiede una copia come la creazione di un elenco dalle chiavi del dizionario.

L'oggetto view ha il meglio di entrambi i mondi: si comporta come un contenitore e tuttavia non crea una copia del dizionario! È, in effetti, una specie di contenitore virtuale di sola lettura che funziona collegandosi al dizionario sottostante. Non so se sia visto altrove nello standard Python.

Modifica:

@AntonyHatchkins: il motivo per cui non restituisce una funzione di generatore è che non consentirebbe un veloce in . Sì, in funziona per le funzioni del generatore (quando le chiamate). Cioè, puoi farlo:

def f():
  for i in range(10):
    yield i

5 in f() # True

Ma secondo la definizione di in , se il lato destro è un generatore, Python passerà attraverso tutti gli elementi n del generatore - portando a O (n) complessità temporale. Non c'è niente che tu possa fare al riguardo perché è l'unico comportamento significativo di un generatore arbitrario.

D'altra parte, nel caso della vista del dizionario, puoi implementare in come preferisci, perché sai di più sui dati che gestisci. E infatti in è implementato con O (1) complessità usando una tabella hash. Puoi verificarlo eseguendo

>>> d = dict(zip(range(50000000), range(50000000)))
>>> 49999999 in d
True
>>> 49999999 in iter(d) # kinda how generator function would work
True
>>>

e notando quanto velocemente il primo in viene confrontato con il secondo in .

Come già accennato nella domanda correlata, view ha il metodo len () , che manca all'iteratore (eppure la lista ce l'ha).

Un altro vantaggio di restituire una vista anziché un elenco è che almeno per le chiavi ha un test di appartenenza ottimizzato nelle operazioni O (1) anziché O (N) per l'elenco (o iteratore).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top