Puis-je écrire une fonction qui détecte si elle est appelée de « with'-déclaration ou non?
-
11-10-2019 - |
Question
Plus précisément, je peux détecter si une fonction est appelée EXPR
dans la déclaration de with EXPR: BLOCK
?
Je suis en train de me familiariser avec l'utilisation de with
-déclaration en python. Dans un premier temps, je réimplémenté un exemple, qui a marqué en texte générer, paru dans la référence de contextlib.contextmanager
(en ignorant la gestion des exceptions pour l'instant).
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>
Cela fonctionne comme prévu. Ensuite, je suis arrivé à penser si tag()
peut également générer des éléments vides:
>>> 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/>
A mes yeux naïfs, il semble faisable si peut détecter si callee est appelée à partir de la déclaration with
ou non. Cependant, je ne sais pas si cette détection est possible ou non. Y at-il une telle façon et, si oui, comment?
La solution
Vous n'êtes pas appeler réellement tag()
« de » la déclaration de with
. Vous appelez tag()
, en faisant passer la valeur de retour de tag()
à la déclaration de with
, qui appelle ensuite __enter__
sur ce passé en valeur, puis exécute le corps, puis appelle __exit__
.
Donc non, vous ne pouvez pas détecter l'instruction with
avant qu'il ne soit effectivement invoqué (qui est après tag()
est appelé).