3
votes

Comment une fonction peut-elle connaître le décorateur de sa fonction appelante?

J'ai deux décorateurs, @timeout et @retry le code est comme ça

@timeout(seconds=1)
def func_inner(expire):
    time.sleep(expire)

@retry(
    count=2,
    message="Failed command after {expire} seconds",
)
def func(expire):
    func_inner(expire)

Je veux juste savoir comment la méthode func () peut savoir que func_inner a un décorateur @timeout? Merci d'avance!


2 commentaires

Copie possible de Comment un décorateur de fonction peut-il être attaché à la fonction à l'intérieur


D'accord, réponse finale, j'ai réédité et inclus trois façons simples de le faire en une seule ligne. Veuillez voir si cela fonctionne pour vous.


3 Réponses :


2
votes

Ce code:

def func_inner(expire):
    time.sleep(expire)

func_inner = timeout(seconds=1)(func_inner)

Est essentiellement égal à:

@timeout(seconds=1)
def func_inner(expire):
    time.sleep(expire)

La méthode func appelle simplement func_inner (expire) , ce qui revient à appeler timeout (seconds = 1) (func_inner) (expire) puisque le décorateur a redéfini la fonction.


0 commentaires

0
votes

La détecter ne serait possible que grâce à un mécanisme spécifique défini par le décorateur lui-même. Un décorateur prend juste une fonction et renvoie un autre objet dans le cas général, et Python lui-même ne garde pas une trace de ce processus.


0 commentaires

1
votes

Oui, vous pouvez voir le wrapper à l'intérieur de la fonction, en utilisant inspect ou globals, et vous pouvez accéder directement à l'objet wrapper.

Voici un exemple simple montrant quelques façons de voir le wrapper à l'intérieur de la fonction. p >

in mywrapper
** myfunc inspect : mywrapper
** myfunc globals : mywrapper
wrapper =
<function mywrapper at 0x7f30df0e72a8>
done myfunc
wrapper =
<function mywrapper at 0x7f30df0e72a8>

Ce qui précède s'imprime,

#!/usr/bin/python
import sys
import inspect

def mydecorator(func):
    def mywrapper():
        print( 'in mywrapper' )
        func()
    return mywrapper

@mydecorator
def myfunc():
    felf = globals()[inspect.getframeinfo(inspect.currentframe()).function]
    print("** myfunc inspect : %s"%felf.__name__)

    felf = globals()[sys._getframe().f_code.co_name]
    print("** myfunc globals : %s"%felf.__name__)

    print( 'wrapper =' )
    print( myfunc )

    print( 'done myfunc' )


myfunc()

print( 'wrapper =' )
print( myfunc )

Notez que le nom n'est pas le nom de votre fonction, mais plutôt le wrapper . Consultez la documentation inspect et getframe pour en savoir plus sur les informations disponibles.


0 commentaires