2013-06-30 23 views
13

io abbiamo lavorato con Python e ho istituito la seguente situazione di codice:Python functools efficienza parziale

import timeit 

setting = """ 
import functools 

def f(a,b,c): 
    pass 

g = functools.partial(f,c=3)  
h = functools.partial(f,b=5,c=3) 
i = functools.partial(f,a=4,b=5,c=3) 
""" 

print timeit.timeit('f(4,5,3)', setup = setting, number=100000) 
print timeit.timeit('g(4,5)', setup = setting, number=100000) 
print timeit.timeit('h(4)', setup = setting, number=100000) 
print timeit.timeit('i()', setup = setting, number=100000) 

ottengo il seguente come risultato:

f: 0.181384086609 
g: 0.39066195488 
h: 0.425783157349 
i: 0.391901016235 

Perché i chiamate al le funzioni parziali richiedono più tempo? La funzione parziale sta semplicemente inoltrando i parametri alla funzione originale o sta mappando gli argomenti statici in tutto? E inoltre, esiste una funzione in Python per restituire il corpo di una funzione compilata dato che tutti i parametri sono predefiniti, come con la funzione i?

risposta

15

Perché le chiamate alle funzioni parziali richiedono più tempo?

Il codice con partial richiede circa due volte più lungo a causa della chiamata di funzione aggiuntiva. Chiamate di funzione are expensive:

funzione chiamata sovraccarico in Python è relativamente elevato, soprattutto in confronto con la velocità di esecuzione di una funzione incorporata.

-

è la funzione parziale solo inoltrare i parametri alla funzione originaria o è la mappatura degli argomenti statiche tutto?

Per quanto ne so - sì, è solo forwards the arguments to the original function.

-

E inoltre, c'è una funzione in Python per restituire il corpo di una funzione compilata dal momento che tutti i parametri sono predefiniti, come con la funzione i?

No, non sono a conoscenza di tale funzione incorporata in Python. Ma penso che sia possibile fare ciò che vuoi, poiché le funzioni sono oggetti che possono essere copiati e modificati.

Ecco un prototipo:

import timeit 
import types 


# http://stackoverflow.com/questions/6527633/how-can-i-make-a-deepcopy-of-a-function-in-python 
def copy_func(f, name=None): 
    return types.FunctionType(f.func_code, f.func_globals, name or f.func_name, 
     f.func_defaults, f.func_closure) 


def f(a, b, c): 
    return a + b + c 


i = copy_func(f, 'i') 
i.func_defaults = (4, 5, 3) 


print timeit.timeit('f(4,5,3)', setup = 'from __main__ import f', number=100000) 
print timeit.timeit('i()', setup = 'from __main__ import i', number=100000) 

che dà:

0.0257439613342 
0.0221881866455 
+0

Grazie per l'aiuto. C'è qualche possibilità che tu o chiunque sia in grado di darmi un consiglio su come farlo? Coinvolgerebbe la manipolazione dell'oggetto byte-code (funzione .__ code__) o può essere eseguita solo attraverso l'oggetto funzione? – user2515310

+0

ho aggiornato la mia risposta. ma sei veramente preoccupato per la velocità? qual è il tuo problema? – warvariuc

+0

Sei assolutamente incredibile. Grazie. E per interesse, sto lavorando su un'API Python e volevo un modo per uno sviluppatore di definire una funzione su un elemento, quindi inserire quella funzione in un ciclo veloce, ma la funzione chiama nell'implementazione Python con cui sto lavorando sono abbastanza proibitivo per accelerare (come si può vedere dai miei risultati timeit. – user2515310