Novice Python coder here coming from a Java background. I'm still puzzled by this:
with open(...) as f:
import numpy as np
File objects are themselves context managers, in that they have
with notifies the
file object when the context is entered and exited (by calling
__exit__, respectively), and this is how a file object "knows" to close the file. There is no wrapper object involved here; file objects provide those two methods (in Java terms you could say that file objects implement the context manager interface).
as is not an alias just like
import module as altname; instead, the return value of
contextmanager.__enter__() is assigned to the target. The
fileobject.__enter__() method returns
self (so the file object itself), to make it easier to use the syntax:
with open(...) as fileobj:
fileobject.__enter__() did not do this but either returned
None or another object, you couldn't inline the
open() call; to keep a reference to the returned file object you'd have to assign the result of
open() to a variable first before using it as a context manager:
fileobj = open(...) with fileobj as something_enter_returned: fileobj.write()
fileobj = open(...) with fileobj: # no as, ignore whatever fileobj.__enter__() produced fileobj.write()
Note that nothing stops you from using the latter pattern in your own code; you don't have to use an
as target part here if you already have another reference to the file object, or simply don't need to even access the file object further.
However, other context managers could return something different. Some database connectors return a database cursor:
conn = database.connect(....) with conn as cursor: cursor.execute(...)
and exiting the context causes the transaction to be committed or rolled back (depending on wether or not there was an exception).