The Python Language Reference, Release 3.9.5 3.3.9 With Statement Context Managers See also: 3.3.10 Special method lookup 41 3.3. Special method names A context manager is an object that defines the runtime context to be established when executing a$_{with}$ statement. The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code. Context managers are normally invoked using the with statement (described in section The with statement ), but can also be used by directly invoking their methods. Typical uses of context managers include saving and restoring various kinds of global state, locking and unlocking resources, closing opened files, etc. For more information on context managers, see typecontextmanager. object. __enter__ ( self$_{)}$ Enter the runtime context related to this object. The with statement will bind this method’s return value to the target(s) specified in the as clause of the statement, if any. object. __exit__ ( self , exc_type , exc_value , traceback ) Exit the runtime context related to this object. The parameters describe the exception that caused the context to be exited. If the context was exited without an exception, all three arguments will be None . If an exception is supplied, and the method wishes to suppress the exception (i.e., prevent it from being prop- agated), it should return a true value. Otherwise, the exception will be processed normally upon exit from this method. Note that __exit__() methods should not reraise the passed-in exception; this is the caller’s responsibility. PEP 343 - The “with” statement The specification, background, and examples for the Python$_{with}$ statement. For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary. That behaviour is the reason why the following code raises an exception: The rationale behind this behaviour lies with a number of special methods such as$_{__hash__()}$ and$_{__repr__()}$ that are implemented by all objects, including type objects. If the implicit lookup of these methods used the conven- tional lookup process, they would fail when invoked on the type object itself: Incorrectly attempting to invoke an unbound method of a class in this way is sometimes referred to as ‘metaclass confusion’, and is avoided by bypassing the instance when looking up special methods: >>> type(1).__hash__ (1)==hash (1) True (continues on next page) >>> 1.__hash__ ()==hash (1) True >>> int.__hash__ ()==hash (int) Traceback (most recent call last): File "<stdin>" , line1, in <module> TypeError: descriptor '__hash__' of 'int' object needs an argument >>> classC : ... pass ... >>> c =C() >>> c.__len__ = lambda :5 >>> len(c) Traceback (most recent call last): File "<stdin>" , line1, in <module> TypeError: object of type 'C' has no len()