开发者

Object becomes None when using a context manager

Why doesn`t this work:

class X:
    var1 开发者_高级运维= 1
    def __enter__(self): pass
    def __exit__(self, type, value, traceback): pass

with X() as z:
    print z.var1

I get:

print z.var1
AttributeError: 'NoneType' object has no attribute 'var1'


Change the definition of X to

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

with assigns the return value of the __enter__() method to the name after as. Your __enter__() returned None, which was assigned to z.

I also changed the class to a new-style class (which is not critical to make it work).


See the docs for context managers:

__enter__( ) Enter the runtime context and return either this object or another object related to the runtime context. The value returned by this method is bound to the identifier in the as clause of with statements using this context manager. An example of a context manager that returns itself is a file object. File objects return themselves from __enter__() to allow open() to be used as the context expression in a with statement.

An example of a context manager that returns a related object is the one returned by decimal.Context.get_manager(). These managers set the active decimal context to a copy of the original decimal context and then return the copy. This allows changes to be made to the current decimal context in the body of the with statement without affecting code outside the with statement.

Your __enter__ method doesn't return anything, which is the same as returning None.


The function you've defined between 'with' and 'as' must have and only have one return value. 'with' will pass the value to its built-in method __enter__().

A class-type object in Python will not return any value if not defined when you called it.

Similarly, if you called a class-type object with its method that returns nothing, it will also throw out exception.

You can't write like this:

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

This generated two return values, and it's even not allowed to pass to one variable in Python.

But this is good to use:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜