【问题标题】:Object becomes None when using a context manager使用上下文管理器时对象变为无
【发布时间】:2011-07-02 21:04:16
【问题描述】:
为什么这不起作用:
class X:
var1 = 1
def __enter__(self): pass
def __exit__(self, type, value, traceback): pass
with X() as z:
print z.var1
我明白了:
print z.var1
AttributeError: 'NoneType' object has no attribute 'var1'
【问题讨论】:
标签:
python
with-statement
【解决方案1】:
你在'with'和'as'之间定义的函数必须有并且只有一个返回值。 'with' 会将值传递给它的内置方法__enter__()。
Python 中的类类型对象如果在调用时未定义,则不会返回任何值。
同样,如果你调用一个类类型的对象,其方法不返回任何内容,它也会抛出异常。
你不能这样写:
with open('file.txt').readlines() as lines:
这产生了两个返回值,在 Python 中甚至不允许传递给一个变量。
但这很好用:
with open('file.txt') as f:
lines = f.readlines()
【解决方案2】:
有关上下文管理器,请参阅 docs:
__enter__( ) 进入运行时上下文并返回此对象或
与运行时相关的另一个对象
语境。这个返回的值
方法绑定到标识符
with 语句的 as 子句 using
这个上下文管理器。一个例子
返回自身的上下文管理器是
一个文件对象。文件对象返回
来自__enter__() 允许
open() 用作上下文
with 语句中的表达式。
上下文管理器示例
返回一个相关的对象是那个
由返回
decimal.Context.get_manager()。这些
经理设置有效小数
原件副本的上下文
十进制上下文,然后返回
复制。这允许进行更改
到当前十进制上下文
with 语句的主体 without
影响 with 之外的代码
声明。
您的__enter__ 方法不返回任何内容,这与返回None 相同。
【解决方案3】:
将X的定义改为
class X(object):
var1 = 1
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
pass
with 将__enter__() 方法的返回值赋给as 之后的名称。你的__enter__()返回了None,它被分配给了z。
我还将该类更改为新样式的类(使其正常工作并不重要)。
【讨论】:
-
有关更多信息,请参阅 PEP 343 link,它很好地描述了语法