Context manager with class methods

Terry Reedy tjreedy at
Fri Sep 23 00:56:54 CEST 2011

On 9/22/2011 6:21 AM, Gavin Panella wrote:

> On Python 2.6 and 3.1 the following code works fine:
>      class Foo(object):
>          @classmethod
>          def __enter__(cls):
>              print("__enter__")
>          @classmethod
>          def __exit__(cls, exc_type, exc_value, traceback):
>              print("__exit__")
>      with Foo: pass

This could be regarded as a bug, see below.

> However, in 2.7 and 3.2 I get:
>      Traceback (most recent call last):
>        File "<stdin>", line 1, in<module>
>      AttributeError: __exit__

type(Foo) == type and type has no such attribute.

Unless otherwise specified, 'method' typically means 'instance method'. 
In particular, the '__xxx__' special methods are (all?) (intended to be) 
instance methods, which is to say, functions that are attributes of an 
object's class. So it is normal to look for special methods on the class 
(and superclasses) of an object rather than starting with the object 
itself. For instance, when executing 'a+b', the interpreter never looks 
for __add__ as an attribute of a itself (in a.__dict__)
but starts the search looking for with type(a).__add__

> Is this a regression or a deliberate change? Off the top of my head I
> can't think that this pattern is particularly useful, but it seems
> like something that ought to work.

I suspect there was a deliberate change to correct an anomaly, though 
this might have been done as part of some other change. As Thomas noted, 
*instances* of Foo work and as Mei noted, making Foo an instance of a 
(meta)class with the needed methods also works.

Terry Jan Reedy

More information about the Python-list mailing list