我正在编写一系列嵌套的上下文,需要跟踪它们的相对关系。但我遇到了以下我没想到的行为:
class NestedContext():
_current = None
def __enter__(self):
self.parent = self._current
self._current = self
def __exit__(self, _type, _value, _tb):
self._current = self.parent
with NestedContext():
assert NestedContext._current is not None # fails
with NestedContext():
pass
断言失败,因为类变量_current
是None,这是意料之外的,因为我认为__enter__
只是将它设置为self。这似乎与我不理解的Python上下文的一些更深层次的行为有关。谁能解释一下?感谢。
答案 0 :(得分:5)
您正在测试类属性。您设置self._current
,实例属性。
如果您想设置class属性,则需要对其进行限定:
class NestedContext(object):
_current = None
def __enter__(self):
self.parent = self._current
NestedContext._current = self
def __exit__(self, _type, _value, _tb):
NestedContext._current = self.parent
当读取属性时,Python会搜索实例,类和基类的层。但是当设置属性时,不会发生这样的分层。因此self._current
如果NestedContext
上没有此类属性,self
会回退到self._current = some_value
,但self
会在object
上设置该属性,而不是在类上。< / p>
我还使用NestedContext
作为_name
的父类;除非有令人信服的理由(例如,您正在处理依赖于旧行为的遗留代码),否则您总是希望获得new style classes。
演示(添加__repr__
属性和>>> class NestedContext(object):
... _current = None
... def __init__(self, name):
... self._name = name
... def __repr__(self):
... return '<NestedContext({._name!r})>'.format(self)
... def __enter__(self):
... self.parent = self._current
... NestedContext._current = self
... def __exit__(self, _type, _value, _tb):
... NestedContext._current = self.parent
...
>>> with NestedContext('outer'):
... print NestedContext._current
... with NestedContext('inner'):
... print NestedContext._current
... print NestedContext._current.parent
...
<NestedContext('outer')>
<NestedContext('inner')>
<NestedContext('outer')>
方法):
{{1}}