[Tutor] Declaration order of classes... why it is important?
Mac Ryan
quasipedia at gmail.com
Fri Aug 28 17:06:07 CEST 2009
On Fri, 2009-08-28 at 08:55 -0400, Dave Angel wrote:
> Mac Ryan wrote:
> > On Wed, 2009-08-26 at 21:32 -0400, Dave Angel wrote:
> >
> >
> >> Now there are a couple of decorators that are in the standard library
> >> that everyone should know about: classmethod() and staticmethod().
> >> They wrap a method in a new one (which ends up having the same name),
> >> such that the first argument is either eaten (staticmethod), or changed
> >> to a class (classmethod).
> >>
> >> Hope that was sufficient detail.
> >>
> >> DaveA
> >>
> >
> > Thank you all for your answer, I read the link posted by Kent end the
> > explanations given by others, and now almost all the pieces of the
> > puzzle are falling to their place.
> >
> > The (last?) thing still escaping my understanding is the difference
> > between classmethod() and staticmethod(). I understand that both of them
> > are to make sure a method will be associated with the class rather than
> > with an instance of it (a bit like variables declared in a class but
> > outside a method), so I assume I should use them like:
> >
> > class myClass(object):
> >
> > @staticmethod / @classmethod
> > def method_of_class(self):
> > pass
> >
> > def method_of_instances(self):
> > pass
> >
> > I am not sure I understood the difference between staticmethod end
> > classmethod, though, even if I can guess it has to do with subclassing,
> > (given classmethod go fish for the class name)... am I on the right
> > track? Any hint (or full-fledged explanation!)? :)
> >
> > [The official documentation is a bit obscure for me as it refers to C#
> > and Java, languages that I do not know.]
> >
> > Also, what is the advantage of using a method at class level rather than
> > using it at object instance (I can imagine you can save some memory by
> > not duplicating X times the same code, maybe... but what kind of designs
> > require/call for use of statc/classmethods?)
> >
> > Thank you in advance for your help,
> > Mac.
> >
> >
> >
> I thought someone (me) had already posted examples. The method itself
> looks different in the three cases:
>
> class MyClass(object):
>
> def my_method1(self, arg):
> ... do something with this particular object
>
> @classmethod
> def my_class_method(cls, arg)
> .... do something that may requires use of class, but
> that doesn't need to know the particular object
>
> @staticmethod
> def my_static_method(arg):
> .... do something which isn't affected at all by what
> class it's in
>
> self and cls parameters are named that merely by convention. Unlike the
> "this" of C++, C#, and Java, these names have no specific meaning to the
> compiler. But convention is a very good thing, especially in this case.
>
> So the first difference between static and class is that the method
> signature must be different. There's an extra parameter on the latter
> that must be included. The second difference is that a classmethod may
> call other methods of the same class, and gets the appropriate methods
> even if the class was subclassed.
>
> The hint to play with is that any of these 3 may be called with an
> object (obj.my_class_method()), and the last two may be called with a
> classname.
>
> DaveA
Thank you Dave, very helpful as ever. I made a few tests and experiments
to understand better, and I feel I am understanding how it works.
Although the mechanic of this is increasingly clear, the logic behind is
still a bit obscure: here comes a silly test on which results I have
questions about
======================================================
class A(object):
variable = 0
@classmethod
def cm(cls):
cls.variable += 3
class B(A):
pass
class C(B):
pass
a = A()
b = B()
c = C()
print A.variable, a.variable
print B.variable, b.variable
print C.variable, c.variable
print '---'
a.cm()
print A.variable, a.variable
print B.variable, b.variable
print C.variable, c.variable
print '---'
b.cm()
print A.variable, a.variable
print B.variable, b.variable
print C.variable, c.variable
print '---'
c.cm()
print A.variable, a.variable
print B.variable, b.variable
print C.variable, c.variable
print '---'
a.variable = 7
A.variable = 4
print A.variable, a.variable
print B.variable, b.variable
print C.variable, c.variable
print '---'
B.variable = 'x'
print A.variable, a.variable
print B.variable, b.variable
print C.variable, c.variable
======================================================
Now, the output of this test is as follows (I manually added the numbers
on the right for reference in the remaining of the post):
0 0 # 1
0 0
0 0
---
3 3 # 2
3 3
3 3
---
3 3 # 3
6 6
6 6
---
3 3 # 4
6 6
9 9
---
4 7 # 5
6 6
9 9
---
4 7 # 6
x x
9 9
#1 is plain obvious.
#2 came as a bit of surprise: "Ah-ah!... so the class variable is the
same for all the hierarchy of classes! I would have guessed each class
had its own variable..."
#3 and #4 are bigger surprises: "Uh? let me understand better, so... it
must be like branches... as soon as I say that B.variable is different
than its ancestors, all the descendants of B get updated... Yet, it's
strange: this very thread on the mailing list has started with me asking
about the order of declaration for classes, and I have been told that
class variables are processed as soon as the interpreter hits the class
definition... so I would have expected that C.variable would have been
initialised already and would not dynamically change when B.variable
does..."
#5 confused me: it seems that a.variable can refer to both the class
variable or a newly created object property... that sounds like a
never-ending source of bugs to me: it is me who has then to remember if
a given syntax refers to a class variable or to an object method?
#6 really make no sense to me: it seems that the class variable of C has
not been changed this time (as it did in #3)...
The points above confuse me even more about the "design purposes" of
classmethods and staticmethods...
Any help/feedback, very much appreciated.
mac.
More information about the Tutor
mailing list