Puedo escribir una función que detecta si se llama desde 'with'-declaración o no?

StackOverflow https://stackoverflow.com/questions/4698064

  •  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?

¿Fue útil?

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top