2012-02-06 16 views
28

È un errore comune impostare un oggetto mutabile come valore predefinito di un argomento in una funzione. Ecco un esempio tratto da this excellent write-up by David Goodger:Buoni usi per i valori predefiniti dell'argomento di funzione mutabile?

>>> def bad_append(new_item, a_list=[]): 
     a_list.append(new_item) 
     return a_list 
>>> print bad_append('one') 
['one'] 
>>> print bad_append('two') 
['one', 'two'] 

La spiegazione per cui questo accade è here.

E ora per la mia domanda: C'è una buona causa d'uso per questa sintassi?

Voglio dire, se tutti quelli che incontra fanno lo stesso errore, lo fa il debug, capisce il problema e da questo cerca di evitarlo, a cosa serve questa sintassi?

+0

Vedere http: // stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument – sdolan

+1

La spiegazione migliore che conosco per questo è nella domanda collegata: le funzioni sono oggetti di prima classe, proprio come le classi. Le classi hanno dati di attributi mutabili; le funzioni hanno valori di default mutabili. – katrielalex

+0

http: // stackoverflow.it/questions/2639915/why-the-mutable-default-argument-fix-syntax-is-so-ugly-chiede-python-newbie – katrielalex

risposta

21

È possibile utilizzarlo per valori di cache tra chiamate di funzione:

def get_from_cache(name, cache={}): 
    if name in cache: return cache[name] 
    cache[name] = result = expensive_calculation() 
    return result 

ma di solito questo genere di cose è fatto meglio con una classe come si può quindi avere attributi aggiuntivi per cancellare la cache ecc

+5

... o un decoratore memoizing. –

+9

'@ functools.lru_cache (maxsize = None)' – katrielalex

+2

@katrielalex lru_cache è nuovo in Python 3.2 quindi non tutti possono usarlo. – Duncan

4
import random 

def ten_random_numbers(rng=random): 
    return [rng.random() for i in xrange(10)] 

Utilizza il modulo random, in modo efficace un singleton mutabile, come generatore di numeri casuali predefinito.

+4

Ma questo non è un caso d'uso terribilmente importante. –

1

MODIFICA (chiarimento): il problema dell'argomento predefinito mutabile è un sintomo di una scelta di progettazione più approfondita, vale a dire che i valori degli argomenti predefiniti sono memorizzati come attributi sull'oggetto funzione. Potresti chiedere perché è stata fatta questa scelta; come sempre, tali domande sono difficili da rispondere correttamente. Ma ha certamente buoni usi:

Ottimizzazione per le prestazioni:

def foo(sin=math.sin): ... 

Afferrando i valori degli oggetti in una chiusura al posto della variabile.

callbacks = [] 
for i in range(10): 
    def callback(i=i): ... 
    callbacks.append(callback) 
+4

numeri interi e funzioni incorporate non sono mutabili! – WolframH

+2

@Jonathan: Non c'è ancora un argomento predefinito mutabile nel restante esempio o semplicemente non lo vedo? – WolframH

+1

@ Jonathan: il mio punto non è che questi sono mutabili. È che il sistema usato da Python per memorizzare gli argomenti predefiniti - sull'oggetto funzione, definito in fase di compilazione - può essere utile. Ciò implica il problema dell'argomento di default mutabile, dal momento che rivalutare l'argomento su ogni chiamata di funzione renderà il trucco inutile. – katrielalex

3

Forse non mutano l'argomento mutevole, ma aspettatevi un argomento mutabile:

def foo(x, y, config={}): 
    my_config = {'debug': True, 'verbose': False} 
    my_config.update(config) 
    return bar(x, my_config) + baz(y, my_config) 

(Sì, lo so è possibile utilizzare config=() in questo caso particolare, ma trovo che meno chiaro . e meno generale)

1

risposta canonica è questa pagina: http://effbot.org/zone/default-values.htm

si menziona anche 3 "buoni" casi d'uso per argomento predefinito mutevole:

  • vincolante variabile locale per valore corrente di variabile esterna in un callback
  • cache/Memoizzazione
  • rilegatura locale dei nomi globali (codice altamente ottimizzato)
+1

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il link per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - [Dalla recensione] (/ recensione/post di bassa qualità/18212166) – Dijkgraaf

Problemi correlati