2011-01-15 7 views
1

Genauer gesagt, kann ich erkennen, ob eine Funktion als EXPR in with EXPR: BLOCK Anweisung aufgerufen wird? Ich versuche, mich mit der Verwendung von with-Anweisung in Python vertraut zu machen. Als ersten Schritt habe ich ein Beispiel implementiert, das markierten Text erzeugt, der in the reference von contextlib.contextmanager erschienen ist (ich ignoriere die Ausnahmebehandlung für jetzt).Kann ich eine Funktion schreiben, die erkennt, ob sie von 'with'-Anweisung aufgerufen wird oder nicht?

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> 

Dies funktioniert wie erwartet. Dann bekam ich zu denken, wenn tag() auch leere Elemente erzeugen können:

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

Zu meiner naiven Augen, so scheint es machbar, wenn Angerufene erkennen kann, wenn sie von with -Anweisung oder nicht genannt wird. Ich weiß jedoch nicht, ob diese Erkennung möglich ist oder nicht. Gibt es so einen Weg, und wenn ja, wie?

+0

Beachten Sie, dass in der Dokumentation "Dies wird nicht als eine echte Art der Generierung von HTML empfohlen wird!" Vielleicht ist das nur ein hypothetisches Beispiel, aber wenn nicht, dann tu das bitte nicht. :) –

+0

Danke für die Erinnerung an mich. Ja, ich war mir dessen bewusst, und diese Frage ist hypothetisch. Wenn die Antwort (von Amber und auch PEP 0343, die ich hätte lesen sollen, bevor ich frage) anders wäre, hätte ich vielleicht ein bisschen mehr geübt, um dieses Konstrukt zum Laufen zu bringen. Leider war es nicht zu sein. Also keine Sorge, diese gescheiterte Verfolgung ist sicher in meinem Kopf eingesperrt :) –

Antwort

5

Sie rufen nicht wirklich tag() "von" der with Anweisung. Sie rufen tag(), übergeben dann den Rückgabewert von tag() an die with-Anweisung, die dann __enter__ auf diesen übergebenen Wert aufruft, dann den Rumpf ausführt und dann __exit__ aufruft.

Also nein, Sie können die with-Anweisung nicht erkennen, bevor sie tatsächlich aufgerufen wird (was nach tag() heißt).

+0

Vielen Dank für eine knappe Antwort. Obwohl Ihre Antwort nicht das ist, was ich hören möchte, erspart es mir, Schatten zu jagen :) –

Verwandte Themen