ClassName.attribute vs self.__class__.attribute

Gabriel Rossetti gabriel.rossetti at arimaz.com
Thu Jun 12 08:52:25 CEST 2008


Mike Orr wrote:
> 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.
>
>   
Yes, I know that
> 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.
>
>   
Ok, I see a use for that now, I also tried a minimal example of my 
problem and it worked as I expected, and thus I am unable to reproduce 
my problem outside of my code. It may be linked to the fact that I am 
using Zope interfaces and Tisted's plugin mechanism, as this problem was 
born in that context ; it's possible that something happens in the 
background that makes it behave strangely. Basically, I the base class 
for the plugins create a class attribute of an object  that is a mutex 
and each subclass solicited it for access to the I/O. The class 
attribute was created only once in it's __init__ (using a conditional 
test). After running it though a debugger, I saw that in reality, every 
Child instantiated it, so every child had it's own mutex, thus they 
could each access the I/O even if it was "supposed" to be locked. I had 
been using "self.__class__.myMutex" everywhere, so I changed it to 
"MyClass.myMutex" and the code behaved correctly. This is what prompted 
me to write this thread. As i said before, I tried reproducing the 
problem out of context, with just regular classes, no interfaces & 
plugin mechanism, and it works as I had expected (originally).
> 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).
>
>   
Yes :-)
> -- Mike Orr <sluggoster at gmail.com>
> --
> http://mail.python.org/mailman/listinfo/python-list
>
>
>   
Gabriel



More information about the Python-list mailing list