[英]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.