ClassName.attribute vs self.__class__.attribute
Gabriel Rossetti
gabriel.rossetti at arimaz.com
Thu Jun 12 02:52:25 EDT 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