Domanda

questo è dal codice sorgente di csv2rec in matplotlib

come può questo funzione di lavoro, se i suoi unici parametri sono 'func, default'?

def with_default_value(func, default):
    def newfunc(name, val):
        if ismissing(name, val):
            return default
        else:
            return func(val)
    return newfunc

IsMissing prende un nome e un valore e determina se la riga deve essere mascherata in un array NumPy.

func sarà o str, int, float o dateparser ... converte dati. Forse non è importante. Mi chiedo solo come si può ottenere un 'nome' e un 'valore'

Sono un principiante. Grazie per eventuali 2Cents! Spero di ottenere abbastanza buono per aiutare gli altri!

È stato utile?

Soluzione

Questa funzione with_default_value è ciò che è spesso definito (impreciso) come "una chiusura" (tecnicamente, la chiusura è piuttosto il funzione interna che viene restituito, qui newfunc - vedi ad esempio qui ). Più genericamente, with_default_value è un funzione di ordine superiore ( "HOF"):. Ci vuole una funzione (func) come argomento, restituisce anche una funzione (newfunc) come risultato

Ho visto risposte confondendo questo con il decoratore concetto e costruire in Python, che è sicuramente non il caso - soprattutto perché si parla func più spesso di essere un incorporato come int. Decoratori sono anche funzioni di ordine superiore, ma piuttosto quelle specifiche: quelle che restituiscono un decorate, cioè "arricchite", versione del loro argomento di una funzione (che deve essere solo argomento - "decoratori con argomenti" si ottengono i più livello della funzione / chiusura nesting, non dando decoratore HOF più di un argomento), che viene riassegnato esattamente lo stesso nome di tale argomento funzione (e quindi ha tipicamente la stessa firma -. utilizzando un decoratore altrimenti sarebbe molto peculiare, non-idiomatica, illeggibile, etc)

Così dimenticare decoratori, che non hanno assolutamente nulla a che fare con il caso, e concentrarsi sulla chiusura newfunc. Una funzione lessicalmente annidata può fare riferimento a (anche se non esegue nuovamente il bind) tutti i nomi delle variabili locali (tra cui nomi degli argomenti, dal momento che gli argomenti sono variabili locali) della funzione di inclusione (s) - è per questo che è noto come chiusura: è "chiuso over" questi "variabili libere". Qui, newfunc può riferirsi a func e default -. E lo fa

Funzioni di ordine superiore sono una cosa molto naturale in Python, soprattutto perché le funzioni sono oggetti di prima classe (quindi non c'è niente di speciale che devi fare per passarli come argomenti, li ritorno, valori di funzione, o anche la loro memorizzazione in liste o altri contenitori, ecc), e non c'è alcuna distinzione dello spazio dei nomi tra le funzioni e gli altri tipi di oggetti, non chiamata automatica di funzioni solo perché sono menzionati, ecc, ecc (e 'più difficile - un po' più difficile, o molto più difficile, a seconda - in altre lingue che fanno disegnare un sacco di distinzioni di questo genere). In Python, che citano una funzione è solo che - una menzione; CALL avviene solo se e quando l'oggetto funzione (indicati per nome, o altro) è seguito da parentesi.

Questo è tutto quello che c'è da questo esempio - per favore sentitevi liberi di modificare la tua domanda, commentare qui, ecc, se c'è qualche altro aspetto specifico che si rimane in dubbio su

Modifica : così il PO commentato cortesemente chiedere altri esempi di "fabbriche di chiusura". Ecco uno - immaginare un qualche tipo astratto di GUI toolkit, e si sta cercando di fare:

for i in range(len(buttons)):
  buttons[i].onclick(lambda: mainwin.settitle("button %d click!" % i))

, ma questo non funziona bene - i all'interno della lambda è tardiva, quindi per il momento un pulsante viene cliccato il valore di i sta andando sempre essere l'indice del pulsante di ultima , non importa quale è stato fatto clic. Ci sono varie soluzioni fattibili, ma una fabbrica di chiusura di un elegante possibilità:

def makeOnclick(message):
  return lambda: mainwin.settitle(message)

for i in range(len(buttons)):
  buttons[i].onclick(makeOnClick("button %d click!" % i))

Qui, stiamo usando la fabbrica di chiusura di modificare il tempo di legame delle variabili -!). In una forma specifica o di un altro, questo è un caso d'uso abbastanza comune per le fabbriche di chiusura

Altri suggerimenti

Questa è una decoratrice Python - fondamentalmente una funzione wrapper. (Articolo dedicato a pittura interni a PEP 318 - http://www.python.org / dev / PEP / pep-0318 / )

Se si guarda attraverso il codice, probabilmente troverete qualcosa di simile:

def some_func(name, val):
    # ...
some_func = with_default_value(some_func, 'the_default_value')

L'intenzione di questo decoratore sembra fornire un valore predefinito se il nome o val argomenti mancano (presumibilmente, se sono impostati su Nessuno).

Per quanto riguarda il motivo per cui funziona:

with_default_value restituisce un oggetto funzione, che è fondamentalmente sarà un copia di quel newfunc nidificato, con il 'func' chiamata e il valore predefinito substited con tutto ciò che è stato passato al with_default_value.

Se qualcuno fa 'foo = with_default_value (bar, 3)', il valore di ritorno è fondamentalmente sarà una nuova funzione:

def foo(name, val):
    ifismissing(name, val):
        return 3
    else:
        return bar(val)

in modo da poter poi prendere quel valore di ritorno, e lo chiamano.

Questa è una funzione che restituisce un'altra funzione. name e value sono i parametri della funzione restituito.

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