2010-03-08 11 views
8

E 'possibile avere una lista ponderata in Python?Python, lista pigra

Per esempio

a = 1 
list = [a] 
print list 
#[1] 
a = 2 
print list 
#[1] 

Se la lista è stata impostata per valutare pigramente poi la linea finale sarebbe [2]

+0

Questo non è quello che ho capito di essere una valutazione pigra. Direi che è più simile a questo: vogliamo trovare i primi 30 numeri positivi il cui quadrato è divisibile per 3. Con un linguaggio desideroso, o codice per prestazioni - 'while (list.length <30) if (i * i % 3 == 0) lista + = i ++; 'o espressività (ma buttando via enormi liste inutili lungo la strada) -' list1 = range 0..10000; per i in list1 if i * i% 3 == 0 list2.add i; list2.trim (30) '.Con i pigri scrivi qualcosa di più simile a quest'ultimo, ma ottieni le prestazioni del primo. Daniel Tao [lo spiega brillantemente] (http://danieltao.com/lazy.js/). –

+0

Un modo pigro potrebbe essere simile a questo: 'range(). Filter (var dove var * var% 3 == 0) .take (30)' - è scritto in modo molto espressivo, ma il codice non viene eseguito in modo imperativo. Viene eseguito: 'range' genera 1.' Filter' - fallisce perché '1 * 1% 3! = 0'. Quindi 'range' genera 2.' Filter' fallisce. Quindi 'range' genera 3.' Filter' passa perché '3 * 3% 3 == 0'. 'Take 'fa la coda come risposta. Dopo che 'take' ha preso 30, l'algoritmo si ferma. Utilizza solo la quantità di memoria necessaria, ma è anche un codice altamente leggibile (e parallelizzabile). –

risposta

10

Il concetto di valutazione "lazy" normalmente viene fornito con linguaggi funzionali, ma in quelli non è possibile riassegnare due valori diversi allo stesso identificatore, quindi, nemmeno lì il vostro esempio può essere riprodotto.

Il punto non è di pigrizia affatto - è che usando un identificatore è garantito essere identici per ottenere un riferimento allo stesso valore che identificatore fa riferimento, e riassegnazione un identificatore, un nudo nome, ad un valore diverso, è garantito per fare in modo che l'identificatore si riferisca ad un valore diverso da loro. Il riferimento al primo valore (oggetto) non viene perso.

Considera un esempio simile in cui la riassegnazione a un nome nudo non è in gioco, ma piuttosto qualsiasi altro tipo di mutazione (per un oggetto mutabile, ovviamente - numeri e stringhe sono immutabili), incluso un assegnamento a qualcosa altro di un nome a nudo:

>>> a = [1] 
>>> list = [a] 
>>> print list 
[[1]] 
>>> a[:] = [2] 
>>> print list 
[[2]] 

Poiché non v'è a - ... che riassegna il nome nuda a, ma piuttosto un a[:] = ... che riassegna a 's contenuti, è banalmente facile fare Python come 'pigro' come desideri (e in effetti ci vorrebbe così mi sforzo di renderlo "desideroso"! -) ... se la pigrizia e l'entusiasmo avevano qualcosa a che fare con entrambi questi casi (che non è così ;-).

Basta essere consapevoli della semantica perfettamente semplice di "assegnazione a un nome spoglio" (rispetto all'assegnazione a qualsiasi altra cosa, che può essere variamente ottimizzata e controllata utilizzando i propri tipi in modo appropriato) e all'illusione ottica di "pigro vs desiderosi di svanire potrebbe sparire ;-)

6

Python è not really very lazy in general.

È possibile utilizzare i generatori per emulare strutture di dati lazy (come liste infinite, eccetera), ma per quanto riguarda le cose come l'uso della sintassi di lista normale, eccetera, non si avrà la pigrizia.

1

È arrivato attraverso questo post quando cercavo una vera implementazione di lista pigra, ma sembrava una cosa divertente da provare e risolvere.

La seguente implementazione non fondamentalmente ciò che è stato originariamente chiesto:

from collections import Sequence 

class LazyClosureSequence(Sequence): 
    def __init__(self, get_items): 
     self._get_items = get_items 

    def __getitem__(self, i): 
     return self._get_items()[i] 

    def __len__(self): 
     return len(self._get_items()) 

    def __repr__(self): 
     return repr(self._get_items()) 

si utilizza in questo modo:

>>> a = 1 
>>> l = LazyClosureSequence(lambda: [a]) 
>>> print l 
[1] 
>>> a = 2 
>>> print l 
[2] 

Questo è ovviamente orribile.