ClassName.attribute vs self.__class__.attribute

Mike Orr sluggoster at gmail.com
Wed Jun 11 16:09:38 EDT 2008


On Jun 5, 8:40 am, Gabriel Rossetti <gabriel.rosse... at arimaz.com>
wrote:
> Hello everyone,
>
> I had read somewhere that it is preferred to use
> self.__class__.attribute over ClassName.attribute to access class (aka
> static) attributes. I had done this and it seamed to work, until I
> subclassed a class using this technique and from there on things started
> screwing up. I finally tracked it down to self.__class__.attribute! What
> was happening is that the child classes each over-rode the class
> attribute at their level, and the parent's was never set,

That's a misunderstanding of classes vs instances.  If you have an
instance of MyClass(Superclass), there is one instance but several
classes.  The instance is of MyClass; there is no instance of
Superclass.  'self' has a .__class__ attribute because it's an
instance, but MyClass and Superclass do not because they're already
classes.

Going further, self.a retrieves the instance attribute if it exists,
or or MyClass.a if it doesn't, or Superclass.a if that doesn't.  But
assigning to self.a always assigns to an instance attribute.  To
assign a class attribute you must use .__class__ or TheClass.
Likewise, to retrieve a class attribute that has been overridden by a
subclass or instance, you must use .__class__ or TheClass.

There's a very good reason to use self.__class__: it makes it possible
to subclass your class.  In Jason Orendorff's path.py, some path
methods return new path objects.  He uses 'path()' rather than
self.__class__ to construct these.  So if you subclass 'path' to
extend it, these methods return path objects rather than your subclass
objects.  In my Unipath package which was written later, I use
self.__class__ in these cases to allow users to extend my class.

It's a little annoying that if you want to print a class's name in
some unknown object, you have to use obj.__class__.__name__ if it's an
instance, and obj.__name__ if it's a class.  I sometimes wish classes
had a .__class__ attribute that's the class itself, but I can see how
that would cause its own confusion (and recursion).

-- Mike Orr <sluggoster at gmail.com>



More information about the Python-list mailing list