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
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
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 !-)
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.
> 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
ACK.
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
> 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
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>
> 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
> 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. :-)
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 !-)
>
> 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'.
> 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
Yeps, same pattern here :-/
Thanks for the correction, anyway.
(snip)
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