Question

J'aime pouvoir mesurer les performances des fonctions de python I de code, donc très souvent je fais quelque chose de similaire à ce ...

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

Oui, je sais que vous êtes censé mesurer la performance avec timeit, mais cela fonctionne très bien pour mes besoins, et me permet de transformer ces informations et de désactiver le débogage très bien.

Ce code de cours a été d'avant, je connaissais les décorateurs de fonction ... Pas que je sache beaucoup sur eux, mais je pense que je pourrais écrire un décorateur qui a fait ce qui suit, en utilisant le ** dictionnaire de kwds:

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

Je voudrais néanmoins dupliquer le travail avant de mes fonctions, de sorte que le travail serait quelque chose comme:

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

Je suppose que cela nécessiterait le décorateur de compter le nombre d'arguments, savent combien la fonction d'origine prendra, la bande tout en excès, passer le bon nombre d'entre eux à la fonction ... Je suis certain que sur la façon dont dire python faire ... Est-il possible? Y at-il une meilleure façon d'atteindre le même?

Était-ce utile?

La solution

Bien que inspecter peut vous être un peu sur le chemin, ce que vous veulent est en général pas possible:

def f(*args):
    pass

Maintenant, combien d'arguments ne f prendre? Depuis *args et **kwargs permettent un nombre arbitraire d'arguments, il n'y a aucun moyen de déterminer le nombre d'arguments d'une fonction nécessite. En fait, il y a des cas où la fonction poignées vraiment autant qu'il y sont jetés à elle!


Modifier si vous êtes prêt à mettre en place avec verbose comme argument de mot-clé spécial, vous pouvez faire ceci:

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))

(Merci Alex Martelli pour la pointe de kwargs.pop!)

Autres conseils

1 sur la réponse de Stephan202, cependant (mettre cela dans une réponse distincte étant donné que les commentaires ne formatez pas bien le code!), Le bit suivant du code dans cette réponse:

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

peut être exprimé plus clairement et de façon concise comme:

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

il peut être difficile, mais vous pouvez faire quelque chose sur ces lignes. Code ci-dessous tente de supprimer des arguments supplémentaires et les 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")

sortie est

func1 has extra args=['x']
func1 has extra args=['y']
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top