I am trying to run this code:
class A:
    def __enter__(self):
        print "enter"
    def __exit__(self, *args):
        print "exit"
    def __init__(self, i):
        self.i = i
with A(10) as a:
    print a.i
And I get this error:
enter
exit
Traceback (most recent call last):
File ".last_tmp.py", line 9, in <module>
print a.i
AttributeError: 'NoneType' object has no attribute 'i'
What is wrong with my syntax?
You will need to return self from __enter__:
def __enter__(self):
    print "enter"
    return self
Your with statement is effectively equivalent to:
a = A(10).__enter__()  # with A(10) as a:
try:
    print a.i  # Your with body
except:
    a.__exit__(exception and type)
    raise
else:
    a.__exit__(None, None, None)
So, you need to return something, otherwise a will have the value of None (default return value), and None does not have an attribute named i, so you get an AttributeError.
The return value of the object's __enter__ method is what is assigned to the name following the as keyword. Your method (implicitly) returns None, resulting in the error you see. Instead, __enter__ should return self, so that the object created by A(10) is assigned to a.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With