【问题标题】: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,它很好地描述了语法
        猜你喜欢
        • 2019-01-22
        • 1970-01-01
        • 2018-07-15
        • 1970-01-01
        • 2021-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-08
        相关资源
        最近更新 更多