2011-01-15 2 views
1

В частности, могу ли я определить, вызвана ли функция как EXPR в заявлении with EXPR: BLOCK? Я пытаюсь понять, как использовать with -statement в python. В качестве первого шага я повторил пример, который генерирует помеченный текст, появился в the referencecontextlib.contextmanager (игнорируя обработку исключений на данный момент).Могу ли я написать функцию, которая обнаруживает, вызвана ли она из инструкции 'with'-statement или нет?

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> 

Это работает должным образом. Тогда, я должен думать, если tag() также может создавать пустые элементы:

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

В моих наивных глазах, кажется выполнимым, если вызываемые могут обнаружить, если он вызывается из with -statement или нет. Однако я не знаю, возможно ли это обнаружение или нет. Есть ли такой способ и, если есть, как?

+0

Обратите внимание, что в документации указано: «Это не рекомендуется в качестве реального способа генерации HTML!» Возможно, это всего лишь гипотетический пример, но если нет, то, пожалуйста, не делайте этого. :) –

+0

Спасибо, что напомнили мне предупреждение. Да, я знал об этом, и этот вопрос гипотетический. Если ответ (от Amber, а также найден PEP 0343, который я должен был прочитать перед запросом), в противном случае, я мог бы немного поработать над тем, чтобы эта конструкция работала. Увы, этого было не должно быть. Так что не волнуйтесь, это неудачное преследование безопасно заперто в моей голове :) –

ответ

5

Вы на самом деле не звоните tag() «из» инструкции with. Вы вызываете tag(), затем передаете возвращаемое значение от tag() к оператору with, которое затем вызывает __enter__ на это переданное значение, затем запускает тело, а затем вызывает __exit__.

Нет, вы не можете обнаружить оператор with до его фактического вызова (который вызывается после tag()).

+0

Благодарим за краткий ответ. Хотя ваш ответ не то, что я хочу услышать, это спасает меня от погони за тенями :) –

Смежные вопросы