Class python 上下文中的变量 class

Class variable in python context class

我正在编写一系列嵌套上下文,需要跟踪它们的相对关系。但是我 运行 以下行为是我没想到的:

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

断言失败,因为 class 变量 _current 是 None,这是意外的,因为我认为 __enter__ 只是将其设置为 self。这似乎与我不理解的 Python 上下文的一些更深层次的行为有关。谁能解释一下?谢谢。

您正在测试 class 属性。您设置 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搜索实例层,class和基础层classes。但是当设置一个属性时,就不会发生这样的分层。因此,如果 self 上没有这样的属性,self._current 将退回到 NestedContext,但是 self._current = some_valueself 上设置该属性,而不是 [=42] =].

我还使用 object 作为 NestedContext 的父 class;除非有令人信服的理由不这样做(例如,您正在使用依赖于旧行为的遗留代码),否则您总是希望获得 new style classes.

演示(添加了 _name 属性和 __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')>