Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ClassName.attribute vs self.__class__.attribute

10 views
Skip to first unread message

Gabriel Rossetti

unread,
Jun 5, 2008, 11:40:39 AM6/5/08
to pytho...@python.org
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, so while I was
thinking that I had indeed a class attribute set in the parent, it was
the child's that was set, and every child had it's own instance! Since
it was a locking mechanism, lots of fun to debug... So, I suggest never
using self.__class__.attribute, unless you don't mind it's children
overriding it, but if you want a truly top-level class attribute, use
ClassName.attribute everywhere!

I wish books and tutorials mentioned this explicitly....

Gabriel

Larry Bates

unread,
Jun 5, 2008, 3:36:17 PM6/5/08
to

If you define a class instance variable with the same name as the class
attribute, how would Python be able to distinguish the two? That is a feature
not a problem. Getter looks for instance attribute, if one is not found it
looks for a class attribute, and upwards. This behavior is used by Zope to do
all sorts of neat stuff.

-Larry Bates

bruno.des...@gmail.com

unread,
Jun 5, 2008, 3:44:43 PM6/5/08
to
On 5 juin, 17:40, Gabriel Rossetti <gabriel.rosse...@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.

It's even prefered to use self.attribute, unless you know you have
both an instance and a class attribute by the same name (but then if
you need to know which one you're accessing then you have a serious
design problem).

> 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,

Which is why it's prefered to access the attribute from the class (or
more simply from the instance which will get them from the class) - a
subclass may have extremly good reasons to have it's own instance of
the attribute.

> and the parent's was never set,

This is another problem.

> so while I was
> thinking that I had indeed a class attribute set in the parent, it was
> the child's that was set, and every child had it's own instance! Since
> it was a locking mechanism, lots of fun to debug...

I can well believe it, and you do have my whole sympathy.

> So, I suggest never
> using self.__class__.attribute, unless you don't mind it's children
> overriding it, but if you want a truly top-level class attribute, use
> ClassName.attribute everywhere!

I would not have expressed it that way. My own experience is that,
most of the time, you do know when it's ok for the subclasses to have
their own instance of the attribute and when it's not, so in the (very
rare) cases it's not ok you use __name_mangling.

Now I'd say that *unknowingly* overriding an attribute of your own
base class when you didn't expect it to happen is mostly a sign that
there's something you don't (didn't ?) quite get wrt/ lookup /
assignment / namespace etc rules in Python.

> I wish books and tutorials mentioned this explicitly....

Possibly. OTHO, if you understand Python's lookup (name resolution)
rules, the difference between MyBaseClass.attrib and
self.__class__.attrib should be obvious. But this surely could be a
good example in a tutorial !-)

Terry Reedy

unread,
Jun 5, 2008, 5:39:18 PM6/5/08
to pytho...@python.org

"Casey McGinty" <casey....@gmail.com> wrote in message
news:ae3f58470806051341s750...@mail.gmail.com...
| On Thu, Jun 5, 2008 at 5:40 AM, Gabriel Rossetti <

| gabriel....@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, so while I was thinking that I had indeed a class attribute set in
the
| > parent, it was the child's that was set, and every child had it's own
| > instance! Since it was a locking mechanism, lots of fun to debug... So,
I
| > suggest never using self.__class__.attribute, unless you don't mind
it's
| > children overriding it, but if you want a truly top-level class
attribute,
| > use ClassName.attribute everywhere!
|
| Thanks for the info. Can anyone explain more about the differences
between
| the two techniques? Why does one work and the other one fail?

If you want to access the attribute of a particular class, to read or
write, use that class.
SomeClass.attr
Note that no instance is required or relevant.

If you want to read the attrubute of the class of an instance (or the first
superclass with the attribute, whatever that class might be, use self.attr
or self.__class__.attr. (Use the latter if the instance has (or might
have) an attribute of the same name).

For setting an attribute, self.attr = x sets it on the instance while
self.__class__.attr = x sets it on its class.

Hrvoje Niksic

unread,
Jun 5, 2008, 5:59:58 PM6/5/08
to
"bruno.des...@gmail.com" <bruno.des...@gmail.com>
writes:

> On 5 juin, 17:40, Gabriel Rossetti <gabriel.rosse...@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.
>
> It's even prefered to use self.attribute,

I was going to write exactly that, but it occurred to me that he might
want to be *assigning* to self.__class__.attribute (or
HisClass.attribute) from his methods, in which case self.attribute
would be quite different.

Gabriel Rossetti

unread,
Jun 6, 2008, 6:19:39 AM6/6/08
to Larry Bates, pytho...@python.org
> --
> http://mail.python.org/mailman/listinfo/python-list
>
>
A class instance variable, you must mean an instance attribute no? If
that is so, then with just self.attribute? Maybe there is a concept that
I don't know about, I've studied class/static attributes and instance
attributes in my OOP classes.

Gabriel

Bruno Desthuilliers

unread,
Jun 6, 2008, 10:35:24 AM6/6/08
to
Hrvoje Niksic a écrit :

ACK.

Bruno Desthuilliers

unread,
Jun 6, 2008, 10:46:08 AM6/6/08
to
Gabriel Rossetti a écrit :

I think that's what he meant, yes.

> If
> that is so, then with just self.attribute? Maybe there is a concept that
> I don't know about,

The concept of name resolution (aka lookup) rules in Python, perhaps ?
When you do obj.attribute, attribute is first looked for in the object,
then in it's class, then in the parent classes. So yes, you can get a
class (or parent class) attribute directly on the instance. Note that
assignment on the instance (obj.attribute = value) will alway (computed
attributes or other hooks excepted) create the attribute on the target,
so if you have Class.attribute set, and then do obj = Class();
obj.attribute = 42, then obj.attribute will shadow Class.attribute.

> I've studied class/static attributes and instance
> attributes in my OOP classes.

Forget about your OOP classes, mostly if it was in fact a Java or C++
class. Python's object model is very far away from what most courses
present as "OOP".

> Gabriel

David C. Ullrich

unread,
Jun 6, 2008, 12:03:56 PM6/6/08
to
In article <mailman.154.1212748...@python.org>,
Gabriel Rossetti <gabriel....@arimaz.com> wrote:

> Larry Bates wrote:
> > Gabriel Rossetti 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, so while I was thinking that I had indeed a
> >> class attribute set in the parent, it was the child's that was set,
> >> and every child had it's own instance! Since it was a locking
> >> mechanism, lots of fun to debug... So, I suggest never using
> >> self.__class__.attribute, unless you don't mind it's children
> >> overriding it, but if you want a truly top-level class attribute, use
> >> ClassName.attribute everywhere!

I shouldn't butt in since everyone else knows more about
this than I do, but it seems to me that saying you should
do this is wrong and saying you should do that is wrong -
which you should do depends on what you're trying to
accomplish.

There's something that comes up all the time in stuff
I do, where implicitly accessing self.__class__.attribute
is vital to make it work right. Say I have a Matrix class,
with an __add__ method:

class Matrix:
def __init__(self, data):
whatever
def __add__(self, other):
newdata = whatever
return Matrix(newdata)

The last line is almost surely not what I want (took
me a while, long ago, to figure this out). Because someday
when I have a subclass I want __add__ to return an instance
of the subclass. At first I thought I needed to rewrite the
last line to return SubClass(newdata). No, I simply return
self.__class__(newdata) and it works exactly the way I want.

> >> I wish books and tutorials mentioned this explicitly....
> >>
> >> Gabriel
> >
> > If you define a class instance variable with the same name as the
> > class attribute, how would Python be able to distinguish the two?
> > That is a feature not a problem. Getter looks for instance attribute,
> > if one is not found it looks for a class attribute, and upwards. This
> > behavior is used by Zope to do all sorts of neat stuff.
> >
> > -Larry Bates
> > --
> > http://mail.python.org/mailman/listinfo/python-list
> >
> >
> A class instance variable, you must mean an instance attribute no? If
> that is so, then with just self.attribute? Maybe there is a concept that
> I don't know about, I've studied class/static attributes and instance
> attributes in my OOP classes.
>
> Gabriel

--
David C. Ullrich

Mike Orr

unread,
Jun 11, 2008, 4:09:38 PM6/11/08
to
On Jun 5, 8:40 am, Gabriel Rossetti <gabriel.rosse...@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 <slugg...@gmail.com>

Gabriel Rossetti

unread,
Jun 12, 2008, 2:52:25 AM6/12/08
to Mike Orr, pytho...@python.org
Mike Orr wrote:
> On Jun 5, 8:40 am, Gabriel Rossetti <gabriel.rosse...@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 <slugg...@gmail.com>
> --
> http://mail.python.org/mailman/listinfo/python-list
>
>
>
Gabriel

Gabriel Rossetti

unread,
Jun 12, 2008, 2:54:30 AM6/12/08
to Bruno Desthuilliers, pytho...@python.org
Ok.

>
>> If that is so, then with just self.attribute? Maybe there is a
>> concept that I don't know about,
>
> The concept of name resolution (aka lookup) rules in Python, perhaps ?
> When you do obj.attribute, attribute is first looked for in the
> object, then in it's class, then in the parent classes. So yes, you
> can get a class (or parent class) attribute directly on the instance.
> Note that assignment on the instance (obj.attribute = value) will
> alway (computed attributes or other hooks excepted) create the
> attribute on the target, so if you have Class.attribute set, and then
> do obj = Class(); obj.attribute = 42, then obj.attribute will shadow
> Class.attribute.
>
Not really, see my answer to Mike Orr's msg.

>> I've studied class/static attributes and instance attributes in my
>> OOP classes.
>
> Forget about your OOP classes, mostly if it was in fact a Java or C++
> class. Python's object model is very far away from what most courses
> present as "OOP".
>
Ok, in some ways yes.
>> Gabriel
> --
> http://mail.python.org/mailman/listinfo/python-list
>
>

Duncan Booth

unread,
Jun 12, 2008, 4:12:00 AM6/12/08
to
Mike Orr <slugg...@gmail.com> wrote:

> 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.

Classes are also instances, usually they are instances of the type 'type'
(and even 'type' is an instance of itself):

>>> class SuperClass(object): pass

>>> SuperClass.__class__
<type 'type'>
>>> type(SuperClass)
<type 'type'>
>>> type.__class__
<type 'type'>

Old style classes don't have a class attribute, but you shouldn't be using
old style classes anyway and so long as you use
type(x)
to access its class rather than accessing the __class__ attribute directly
that doesn't particularly matter.


--
Duncan Booth http://kupuguy.blogspot.com

Hrvoje Niksic

unread,
Jun 12, 2008, 4:19:16 AM6/12/08
to
Mike Orr <slugg...@gmail.com> writes:

> There's a very good reason to use self.__class__: it makes it
> possible to subclass your class.

This really depends on the usage. In the OP's use case, he wanted the
subclasses to share the same lock object defined in the superclass
(because of synchronization), so it would have been wrong to use
self.__class__ *because* of subclassing.

Also note that for new-style classes, self.__class__ can be spelled as
type(self), since there is no distinction between classes and types.

> 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).

They do, the metaclass. :-)

Bruno Desthuilliers

unread,
Jun 12, 2008, 5:17:49 AM6/12/08
to
Mike Orr a écrit :
(snip)

> 'self' has a .__class__ attribute because it's an
> instance, but MyClass and Superclass do not because they're already
> classes.

Not true for new-style classes:

>>> class Toto(object): pass
...
>>> Toto.__class__
<type 'type'>


(snip)

> I sometimes wish classes
> had a .__class__ attribute that's the class itself,

newstyle classes do have a class attribute, that refers to the metaclass.

> but I can see how
> that would cause its own confusion (and recursion).

FWIW, metaclasses do have a class attribute that refers to itself !-)

Duncan Booth

unread,
Jun 12, 2008, 6:40:34 AM6/12/08
to
Bruno Desthuilliers <bruno.42.de...@websiteburo.invalid> wrote:

>
> FWIW, metaclasses do have a class attribute that refers to itself !-)
>

One metaclass (i.e. type) has a class attribute that refers to itself.

Other metaclasses have a class attribute that refers to the metaclass's
metaclass. I can't think of any situation where a metaclass would be its
own metaclass except for 'type' itself, but then I think I've got a
headache trying to think about this so maybe I'm wrong.

In fact, thinking about it a bit more, I think that if you did have another
metaclass which is its own metaclass then the class cannot subclass
'object'.

Hrvoje Niksic

unread,
Jun 12, 2008, 8:50:40 AM6/12/08
to
Duncan Booth <duncan...@invalid.invalid> writes:

> In fact, thinking about it a bit more, I think that if you did have
> another metaclass which is its own metaclass then the class cannot
> subclass 'object'.

You could if the metaclass of your metaclass inherited from 'type'.
Then your types could still be binary-compatible with Python types,
and your objects with 'object'. It's difficult to envision what you'd
gain with a custom meta-meta-class, but it seems possible:

>>> class MetaMeta(type): pass
...
>>> class Meta(type):
... __metaclass__ = MetaMeta
...
>>> class Foo(object):
... __metaclass__ = Meta
...
>>> f = Foo()
>>> f
<__main__.Foo object at 0xb7d27bec>
>>> type(f)
<class '__main__.Foo'>
>>> type(type(f))
<class '__main__.Meta'>
>>> type(type(type(f)))
<class '__main__.MetaMeta'>
>>> isinstance(f, object)
True

Gabriel Rossetti

unread,
Jun 13, 2008, 2:33:52 AM6/13/08
to duncan...@suttoncourtenay.org.uk, pytho...@python.org
Duncan Booth wrote:
> Mike Orr <slugg...@gmail.com> wrote:
>
>
>> 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.
>>
>
> Classes are also instances, usually they are instances of the type 'type'
> (and even 'type' is an instance of itself):
>
>
Ok, I didn't know that

>>>> class SuperClass(object): pass
>>>>
>
>
>>>> SuperClass.__class__
>>>>
> <type 'type'>
>
>>>> type(SuperClass)
>>>>
> <type 'type'>
>
>>>> type.__class__
>>>>
> <type 'type'>
>
> Old style classes don't have a class attribute, but you shouldn't be using
> old style classes anyway and so long as you use
> type(x)
> to access its class rather than accessing the __class__ attribute directly
> that doesn't particularly matter.
>
>
Yes, I don't use old style classes

Bruno Desthuilliers

unread,
Jun 13, 2008, 3:00:35 AM6/13/08
to
Duncan Booth a écrit :

> Bruno Desthuilliers <bruno.42.de...@websiteburo.invalid> wrote:
>
>> FWIW, metaclasses do have a class attribute that refers to itself !-)
>>
> One metaclass (i.e. type) has a class attribute that refers to itself.
>
> Other metaclasses have a class attribute that refers to the metaclass's
> metaclass. I can't think of any situation where a metaclass would be its
> own metaclass except for 'type' itself, but then I think I've got a
> headache trying to think about this

Yeps, same pattern here :-/

Thanks for the correction, anyway.
(snip)

Terry Reedy

unread,
Jun 13, 2008, 5:39:27 PM6/13/08
to pytho...@python.org

"> One metaclass (i.e. type) has a class attribute that refers to itself.
>
> Other metaclasses have a class attribute that refers to the metaclass's
> metaclass. I can't think of any situation where a metaclass would be its
> own metaclass except for 'type' itself, but then I think I've got a
> headache trying to think about this

In 3.0, with old classes gone and all classes called 'classes'*:

All objects are instances of base class 'object', nearly always indirectly
via subclasses of 'object'. All classes are subclasses of 'object',
including base metaclass 'type'. The methods of 'object' are the methods
that apply to objects as objects in general, as instances. Many of these
are 'base methods' that get overridden in subclasses to fit their
instances.

All classes (including object and type, dropping the quotes) are instances
of type, usually directly but occassionally via subclasses of type. In
other words, the subclass type defines the subclass of objects that are
classes. The additional attributes and methods of type (beyond those
inherited from object ) are, therefore, those that specifically apply to
all classes. These include __call__, by which classes (including 'object'
and 'type' itself) make instances.

The circularity conundrum is that type is a subclass of object while the
immutable class attribute of both object and type is type. The answer, of
course, is that a Python interpreter, as god of a Python universe, creates
both 'ex nihilo', from nothing, with the required attributes.

* In 3.0a5+
>>> type(type)
<class 'type'> # instead of <type 'type'>, and so on.

Terry Jan Reedy

0 new messages