Posso scrivere una funzione che rileva se viene chiamato da 'with'-dichiarazione o no?
-
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?
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).