22

为什么这不起作用:

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'
4

3 回答 3

38

将定义更改X

class X(object):
    var1 = 1
    def __enter__(self):
        return self
    def __exit__(self, type, value, traceback):
        pass

with将方法的返回值赋给__enter__()之后的名称as。您的__enter__()退回None,分配给z.

我还将课程更改为新式课程(使其工作并不重要)。

于 2011-02-23T16:04:09.203 回答
7

请参阅上下文管理器的文档:

__enter__( )输入运行时上下文并返回此对象或与运行时上下文相关的另一个对象。此方法返回的值绑定到使用此上下文管理器的 with 语句的 as 子句中的标识符。返回自身的上下文管理器的一个示例是文件对象。文件对象返回自身__enter__()以允许 open()用作 with 语句中的上下文表达式。

返回相关对象的上下文管理器的一个示例是由 decimal.Context.get_manager(). 这些管理器将活动十进制上下文设置为原始十进制上下文的副本,然后返回该副本。这允许在 with 语句的主体中对当前十进制上下文进行更改,而不会影响 with 语句之外的代码。

您的__enter__方法不返回任何内容,这与返回相同None

于 2011-02-23T16:06:01.913 回答
2

您在 'with' 和 'as' 之间定义的函数必须具有且只有一个返回值。'with' 会将值传递给它的内置方法__enter__()

Python 中的类类型对象如果在调用时未定义,则不会返回任何值。

同样,如果你调用一个类类型的对象,它的方法不返回任何内容,它也会抛出异常。

你不能这样写:

with open('file.txt').readlines() as lines:

这产生了两个返回值,甚至不允许在 Python 中传递给一个变量。

但这很好用:

with open('file.txt') as f:
    lines = f.readlines()
于 2019-07-24T01:32:01.630 回答