简体   繁体   English

python上下文类中的类变量

[英]Class variable in python context class

I am writing a series of nested contexts, and need to keep trace of their relative relationship. 我正在编写一系列嵌套的上下文,并且需要跟踪它们的相对关系。 But I ran in the following behavior that I did not expect: 但是我遇到了以下我没有想到的行为:

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

The assert fail because the class variable _current is None, which is unexpected, since I thought __enter__ just set it to self. 断言失败是因为类变量_current为None,这是意外的,因为我认为__enter__只是将其设置为self。 This seems to be related some deeper behavior of Python context that I don't understand. 这似乎与我不了解的Python上下文的一些更深层次的行为有关。 Can anyone explain? 谁能解释? Thanks. 谢谢。

You are testing the class attribute . 您正在测试class属性 You set self._current , an instance attribute . 您设置了self._current 实例属性

If you wanted to set the class attribute, you need to qualify it as such: 如果要设置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

When reading an attribute, Python searches through the layers of instance, class, and base classes. 读取属性时,Python会搜索实例,类和基类的各个层。 But when setting an attribute, no such layering takes place. 但是在设置属性时,不会发生这种分层。 So self._current will fall back to NestedContext if there is no such attribute on self , but self._current = some_value sets that attribute on self , not on the class. 因此,如果self上没有这样的属性,那么self._current将回NestedContext ,但是self._current = some_value属性设置为self ,而不是在类上。

I also used object as the parent class for NestedContext ; 我还使用object作为NestedContext的父类; unless there are compelling reasons not to (eg you are working with legacy code that relies on the old behaviours), you always want to get new style classes . 除非有令人信服的理由不这样做(例如,您正在使用依赖于旧行为的遗留代码),否则您始终希望获得新的样式类

Demo (with addition of a _name attribute and a __repr__ method): 演示(添加_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')>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM