问题
I've read that the object's __ enter__() and __ exit__() methods are called every time 'with' is used. I understand that for user-defined objects, you can define those methods yourself, but I don't understand how this works for built-in objects/functions like 'open' or even the testcases.
This code works as expected and I assume it closes the file with __ exit__():
with open('output.txt', 'w') as f:
f.write('Hi there!')
or
with self.assertRaises(ValueError):
remove_driver(self.driver) # self refers to a class that inherits from the default unittest.TestCase
Yet, there's no such __ enter__() or __ exit__() method on either object when I inspect it:
So how is 'open' working with 'with'? Shouldn't objects that support context management protocol have __ enter__() and __ exit__() methods defined and inspectable?
回答1:
open()
is a function. It returns something that has an __enter__
and __exit__
method. Look at something like this:
>>> class f:
... def __init__(self):
... print 'init'
... def __enter__(self):
... print 'enter'
... def __exit__(self, *a):
... print 'exit'
...
>>> with f():
... pass
...
init
enter
exit
>>> def return_f():
... return f()
...
>>> with return_f():
... pass
...
init
enter
exit
Of course, return_f
itself does not have those methods, but what it returns does.
回答2:
open
is a function that returns a file object with the context methods, and self.assertRaises
is a method that returns an object with the context methods, try checking the dir
of their return value:
>>> x = open(__file__, "r")
>>> x
<_io.TextIOWrapper name='test.py' mode='r' encoding='US-ASCII'>
>>> type(x)
<class '_io.TextIOWrapper'>
>>> "__exit__" in dir(x)
True
回答3:
You're checking whether the open
function itself or the assertRaises
method itself has __enter__
and __exit__
methods, when you should be looking at what methods the return value has.
来源:https://stackoverflow.com/questions/38666733/where-is-a-python-built-in-objects-enter-and-exit-defined