Python Language
Modulo Functools
Ricerca…
parziale
La funzione partial
crea un'applicazione di funzione parziale da un'altra funzione. Viene utilizzato per associare valori ad alcuni argomenti della funzione (o argomenti della parola chiave) e produrre un callable senza gli argomenti già definiti.
>>> from functools import partial
>>> unhex = partial(int, base=16)
>>> unhex.__doc__ = 'Convert base16 string to int'
>>> unhex('ca11ab1e')
3390155550
partial()
, come suggerisce il nome, consente una valutazione parziale di una funzione. Diamo un'occhiata al seguente esempio:
In [2]: from functools import partial
In [3]: def f(a, b, c, x):
...: return 1000*a + 100*b + 10*c + x
...:
In [4]: g = partial(f, 1, 1, 1)
In [5]: print g(2)
1112
Quando g
viene creato, f
, che prende quattro argomenti ( a, b, c, x
), viene anche parzialmente valutato per i primi tre argomenti, a, b, c,
La valutazione di f
è completata quando g
è chiamato, g(2)
, che passa il quarto argomento a f
.
Un modo di pensare partial
è un registro a scorrimento; spingendo in un argomento alla volta in qualche funzione. partial
è utile per i casi in cui i dati arrivano come stream e non possiamo passare più di un argomento.
total_ordering
Quando vogliamo creare una classe ordinabile, normalmente dobbiamo definire i metodi __eq()__
, __lt__()
, __le__()
, __gt__()
e __ge__()
.
Il decoratore total_ordering
, applicato a una classe, consente la definizione di __eq__()
e solo uno tra __lt__()
, __le__()
, __gt__()
e __ge__()
, e consente comunque tutte le operazioni di ordinamento sulla classe.
@total_ordering
class Employee:
...
def __eq__(self, other):
return ((self.surname, self.name) == (other.surname, other.name))
def __lt__(self, other):
return ((self.surname, self.name) < (other.surname, other.name))
Il decoratore usa una composizione dei metodi forniti e delle operazioni algebriche per ricavare gli altri metodi di confronto. Ad esempio, se abbiamo definito __lt__()
e __eq()__
e vogliamo derivare __gt__()
, possiamo semplicemente controllare not __lt__() and not __eq()__
.
Nota : la funzione total_ordering
è disponibile solo da Python 2.7.
ridurre
In Python 3.x, la funzione di reduce
già illustrata qui è stata rimossa dai built-in e deve ora essere importata da functools
.
from functools import reduce
def factorial(n):
return reduce(lambda a, b: (a*b), range(1, n+1))
lru_cache
Il decoratore @lru_cache
può essere utilizzato per avvolgere una funzione costosa e ad alta intensità di calcolo con una cache meno recente . Ciò consente di memorizzare le chiamate di funzione, in modo che le chiamate future con gli stessi parametri possano tornare istantaneamente invece di dover essere ricalcolate.
@lru_cache(maxsize=None) # Boundless cache
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
>>> fibonacci(15)
Nell'esempio sopra, il valore di fibonacci(3)
viene calcolato solo una volta, mentre se fibonacci
non ha una cache LRU, fibonacci(3)
sarebbe stato calcolato verso l'alto di 230 volte. Quindi @lru_cache
è particolarmente adatto per funzioni ricorsive o programmazione dinamica, in cui una funzione costosa può essere chiamata più volte con gli stessi parametri esatti.
@lru_cache
ha due argomenti
-
maxsize
: numero di chiamate da salvare. Quando il numero di chiamate univoche supera il numeromaxsize
, la cache della LRU rimuoverà le chiamate utilizzate meno di recente. -
typed
(aggiunto in 3.3): Flag per determinare se argomenti equivalenti di tipi diversi appartengono a diversi record della cache (cioè se3.0
e3
contano come argomenti diversi)
Possiamo anche vedere le statistiche della cache:
>>> fib.cache_info()
CacheInfo(hits=13, misses=16, maxsize=None, currsize=16)
NOTA : Poiché @lru_cache
utilizza i dizionari per memorizzare i risultati nella cache, tutti i parametri per la funzione devono essere lavabili affinché la cache funzioni.
Documenti ufficiali di Python per @lru_cache
. @lru_cache
stato aggiunto in 3.2.
cmp_to_key
Python ha cambiato i suoi metodi di ordinamento per accettare una funzione chiave. Queste funzioni prendono un valore e restituiscono una chiave che viene utilizzata per ordinare gli array.
Vecchie funzioni di confronto usate per prendere due valori e restituiscono -1, 0 o +1 se il primo argomento è piccolo, uguale o maggiore del secondo argomento rispettivamente. Questo è incompatibile con la nuova funzione chiave.
Ecco dove arriva functools.cmp_to_key
:
>>> import functools
>>> import locale
>>> sorted(["A", "S", "F", "D"], key=functools.cmp_to_key(locale.strcoll))
['A', 'D', 'F', 'S']
Esempio preso e adattato dalla documentazione della libreria standard Python .