Puedo escribir una función que detecta si se llama desde 'with'-declaración o no?
-
11-10-2019 - |
Pregunta
Más específicamente, puedo detectar si una función se llama como en la declaración EXPR
with EXPR: BLOCK
?
Estoy tratando de hacerme familiarizado con el uso de with
-declaración en Python. Como primer paso, reimplementado un ejemplo, que generan marcado de texto, aparecido en el referencia de contextlib.contextmanager
(ignorando el manejo de excepciones por ahora).
class Markup(object):
def __init__(self):
self.tags = []
self.append = self.tags.append
self.pop = self.tags.pop
def tag(self, name):
self.append(name)
return self
def __enter__(self):
print('<{}>'.format(self.tags[-1]))
def __exit__(self, exc_type, exc_value, traceback):
print('</{}>'.format(self.pop()))
>>> m = Markup()
>>> with m.tag('ELEMENT'):
... print('sample text')
...
<ELEMENT>
sample text
</ELEMENT>
Esto funciona como se esperaba. Entonces, llegué a pensar si tag()
también puede generar elementos vacíos:
>>> m = Markup()
# if a function appears as EXPR of "with EXPR: BLOCK", 'ELEMENT' is a container element. .
>>> with m.tag('ELEMENT'):
... print('sample text')
...
<ELEMENT>
sample text
</ELEMENT>
# in other cases, ELEMENT is an empty element.
>>> m.tag('ELEMENT')
<ELEMENT/>
Para los ojos ingenuos, parece factible si destinatario de la llamada puede detectar si se llama desde with
-declaración o no. Sin embargo, no sé si esta detección es posible o no. ¿Hay alguna manera y, si existe, ¿cómo?
Solución
Usted no está realmente llamando tag()
"de" la declaración with
. Estás llamando tag()
, a continuación, pasar el valor de retorno de tag()
a la declaración with
, que a su vez llama a __enter__
en ese pasado-en valor, a continuación, se ejecuta el cuerpo, a continuación, llama __exit__
.
Así que no, no se puede detectar el estado de with
antes de que se invoca realmente (lo que se llama después de tag()
es).