Posso scrivere una funzione che rileva se viene chiamato da 'with'-dichiarazione o no?

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

  •  11-10-2019
  •  | 
  •  

Domanda

In particolare, posso rilevare se una funzione si chiama come EXPR nella dichiarazione with EXPR: BLOCK? Sto cercando di farmi conoscere l'utilizzo di with-statement in Python. Come primo passo, ho ri-implementato un esempio, che generano marcato del testo, apparso in riferimento contextlib.contextmanager (ignorando gestione delle eccezioni per ora).

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>

Questo funziona come previsto. Poi, ho avuto modo di pensare se tag() può anche generare elementi vuoti:

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

Ai miei occhi ingenui, sembra fattibile se callee in grado di rilevare se viene chiamato da with-dichiarazione o no. Tuttavia, non so se questo rilevamento è possibile o no. Esiste un modo e, se c'è, come?

È stato utile?

Soluzione

Non sta effettivamente chiamando tag() "da" la dichiarazione with. Si sta chiamando tag(), passando poi il valore restituito dal tag() la dichiarazione with, che quindi chiama __enter__ su quel valore passato, poi corre il corpo, poi chiama __exit__.

Quindi no, non è possibile rilevare la dichiarazione with prima che sia effettivamente invocato (che viene dopo tag() si chiama).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top