Pregunta

Me gusta ser capaz de medir el desempeño de las funciones de Python I de código, por lo que muy a menudo hago algo similar a esto ...

import time

def some_function(arg1, arg2, ..., argN, verbose = True) :
    t = time.clock() # works best in Windows
    # t = time.time() # apparently works better in Linux

    # Function code goes here

    t = time.clock() - t
    if verbose :
        print "some_function executed in",t,"sec."

    return return_val

Sí, ya sé que se supone para medir el desempeño con timeit, pero esto funciona muy bien para mis necesidades, y me permite convertir esta información de forma intermitente durante la depuración muy bien.

Ese código, por supuesto, fue desde antes de conocer los decoradores de funciones ... No es que sepa mucho acerca de ellos ahora, pero creo que podría escribir un decorador que hizo lo siguiente, utilizando el diccionario kwds **:

some_function(arg1, arg2, ..., argN) # Does not time function
some_function(arg1, arg2, ..., argN, verbose = True) # Times function

Me gustaría, sin embargo, para duplicar el trabajo previo de mis funciones, por lo que el trabajo sería algo más parecido a:

some_function(arg1, arg2, ..., argN) # Does not time function
some_function(arg1, arg2, ..., argN, False) # Does not time function
some_function(arg1, arg2, ..., argN, True) # Times function

Creo que esto requeriría el decorador para contar el número de argumentos, sabe cuántos la función original se llevará, despojar a cualquier superior, pase el número correcto de ellos a la función ... Estoy seguro de que en la forma para contar pitón de hacer esto ... ¿es posible? ¿Hay una mejor manera de lograr lo mismo?

¿Fue útil?

Solución

inspeccionar pueden conseguir que un poco en el camino, lo que quieren es en general no sea posible:

def f(*args):
    pass

Ahora, ¿cuántos argumentos hace f tomar? Desde *args y **kwargs permiten para un número arbitrario de argumentos, no hay manera de determinar el número de argumentos una función requiere. De hecho, hay casos en los que la función realmente maneja tantos como son arrojados en él!


Editar si usted está dispuesto a soportar verbose como un argumento especial de palabras clave, usted puede hacer esto:

import time

def timed(f):
    def dec(*args, **kwargs):
        verbose = kwargs.pop('verbose', False)
        t = time.clock()

        ret = f(*args, **kwargs)

        if verbose:
            print("%s executed in %ds" % (f.__name__, time.clock() - t))

        return ret

    return dec

@timed
def add(a, b):
    return a + b

print(add(2, 2, verbose=True))

( Alex Martelli por la punta kwargs.pop!)

Otros consejos

1 en la respuesta de Stephan202, sin embargo (poner esto en una respuesta por separado ya que los comentarios no da formato correctamente código!), El siguiente fragmento de código en el que la respuesta:

verbose = False
if 'verbose' in kwargs:
     verbose = True
     del kwargs['verbose']

puede expresarse mucho más clara y concisamente como:

verbose = kwargs.pop('verbose', False)

podría ser difícil, pero se puede hacer algo sobre estas líneas. Código de abajo intenta quitar cualquier argumentos adicionales y las imprime.

def mydeco(func):
    def wrap(*args, **kwargs):
        """
        we want to eat any extra argument, so just count args and kwargs
        and if more(>func.func_code.co_argcount) first take it out from kwargs 
        based on func.func_code.co_varnames, else last one from args
        """
        extraArgs = []

        newKwargs = {}
        for name, value in kwargs.iteritems():
            if name in func.func_code.co_varnames:
                newKwargs[name] = value
            else:
                extraArgs.append(kwargs[name])

        diff = len(args) + len(newKwargs) - func.func_code.co_argcount
        if diff:
            extraArgs.extend(args[-diff:])
            args = args[:-diff]

        func(*args, **newKwargs)
        print "%s has extra args=%s"%(func.func_name, extraArgs)

    return wrap

@mydeco
def func1(a, b, c=3):
    pass

func1(1,b=2,c=3, d="x")
func1(1,2,3,"y")

salida es

func1 has extra args=['x']
func1 has extra args=['y']
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top