Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With statement sets variable to None

Tags:

python

syntax

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?

like image 491
Kipi Avatar asked Dec 14 '22 19:12

Kipi


2 Answers

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.

like image 121
matsjoyce Avatar answered Jan 04 '23 11:01

matsjoyce


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.

like image 38
chepner Avatar answered Jan 04 '23 10:01

chepner