Cómo usar un administrador de contexto dentro de un decorador y cómo pasar un objeto creado en decorador a función decorada

Tengo una clase de prueba que requiere hacer un poco de limpieza al final. Para asegurarme de que el usuario no se olvide de hacer esto, quiero agregar un administrador de contexto a la clase. También tengo un decorador, dentro del cual quiero usar este administrador de contexto para crear un objeto de clase de prueba y pasarlo a la función decorada. ¿Es incluso posible?

Esto es lo que estoy buscando hacer:

class test: def __init__(self, name): self._name = name print "my name is {0}".format(name) def exit(): print "exiting" @contextmanager def testcm(self): print "inside cm" try: yield self finally: self.exit() def randomtest(self, str): print "Inside random test {0}".format(str) def decorate(name): def wrapper(testf): def testf_wrapper(test): with test(name).testcm() as testobj: return testf(testobj) return testf_wrapper return wrapper return decorate @decorate("whatever") def testf(testobj): testobj.randomtest("randomness") 

La función testf toma el objeto de clase de prueba – testobj y hace cosas con él. Luego, debido al administrador de contexto, testcm se asegura de que se testcm la función de limpieza.

Así que hay dos preguntas:

  1. ¿Cómo uso un administrador de contexto dentro de un decorador? De lo que sé, un decorador debe devolver una función, pero si devuelvo la función (como en el código anterior), ¿cómo podría el administrador de contexto llamar a la limpieza?

  2. ¿Cómo paso un objeto creado en decorador a la función decorada, si lo paso como en el código anterior, cómo llamaría la función decorada?

Su progtwig de ejemplo tiene varios errores, y me perdí en toda la redundancia test / testf / testobj . Permítame dirigir sus preguntas directamente.

¿Cómo uso un administrador de contexto dentro de un decorador?

Exactamente como usarías un administrador de contexto en cualquier otro lugar. Considere este progtwig, que utiliza un decorador para convertir de forma transparente str en un file al invocar una función:

 def opener(func): def wrapper(name): with open(name) as input_file: func(input_file) return wrapper @opener def first_line(fd): print fd.readline() first_line('/etc/passwd') 

Como puede ver, la función decoradora utiliza un administrador de contexto alrededor de la invocación de la función decorada.

¿Cómo paso un objeto creado en decorador a la función decorada, si lo paso como en el código anterior, cómo llamaría la función decorada?

Exactamente como pasarías un objeto a cualquier función. Ver mi ejemplo anterior. El decorador crea un objeto de file y lo pasa a la función decorada.


Para completar, aquí está su progtwig de ejemplo con los errores corregidos:

 from contextlib import contextmanager class test: def __init__(self, name): self._name = name print "my name is {0}".format(name) def exit(self): print "exiting" @contextmanager def testcm(self): print "inside cm" try: yield self finally: self.exit() def randomtest(self, str): print "Inside random test {0}".format(str) def decorate(name): def wrapper(testf): def testf_wrapper(): with test(name).testcm() as testobj: return testf(testobj) return testf_wrapper return wrapper @decorate("whatever") def testf(testobj): testobj.randomtest("randomness") testf()