classmethods, class variables and subclassing

Steve Holden steve at holdenweb.com
Thu Oct 20 17:17:28 EDT 2005


Andrew Jaffe wrote:
> Hi,
> 
> I have a class with various class-level variables which are used to 
> store global state information for all instances of a class. These are 
> set by a classmethod as in the following (in reality the setcvar method 
> is more complicated than this!):
> 
> class sup(object):
>      cvar1 = None
>      cvar2 = None
> 
>      @classmethod
>      def setcvar1(cls, val):
>          cls.cvar1 = val
> 
>      @classmethod
>      def setcvar2(cls, val):
>          cls.cvar2 = val
> 
>      @classmethod
>      def printcvars(cls):
> 	print cls.cvar1, cls.cvar2
> 
> 
> I can then call setcvar on either instances of the class or the class 
> itself.
> 
> Now, the problem comes when I want to subclass this class. If I 
> override the setcvar1 method to do some new things special to this 
> class, and then call the sup.setcvar1() method, it all works fine:
> 
> class sub(sup):
>      cvar1a = None
> 
>      @classmethod
>      def setcvar1(cls, val, vala):
>          cls.cvar1a = vala
>          sup.setcvar1(val)
> 
>      @classmethod
>      def printcvars(cls):
>          print cls.cvar1a
>          sup.printcvars()
> 
> This works fine, and sets cvar and cvar2 for both classes.
> 
> However, if  I *don't* override the setcvar2 method, but I call 
> sub.setcvar2(val) directly, then only sub.cvar2 gets set; it is no 
> longer identical to sup.cvar1!
> 
> In particular,
>      sub.setcvar1(1,10)
>      sub.setcvar2(2)
>      sub.printcvars()
> prints
>    10
>    1 None
> 
> i.e. sub.cvar1, sub.cvar1a, sub.cvar2= 1 10 2
> but sup.cvar1, cvar2= 1 None
> 
> since sup.cvar2 has never been set, and this is what sup.printcvars() 
> looks for.
> 
> This behavior is "expected", but is it desirable?
> 
> For my application, at least, I think the problem really comes in the 
> printcvars method: is there any way to call the overridden 
> sup.printcvars() but with, effectively, cls=sub?
> 
> Thanks for reading this far!
> 
> Andrew
> 
> 
> Andrew
> 
> 
> 
> 
> This seems like a bug
> 
> Is this expected behavior, or a bug (or both -- it is expected but 
> probably not what is wanted!)?

You are experiencing this problem because you are using hard-wired class 
names. Try using (for example) self.__class__. That way, even if your 
method is inheroted by a subclass it will use the class of the object it 
finds itself a method of. No need to use classmethods.

regards
  Steve
-- 
Steve Holden       +44 150 684 7255  +1 800 494 3119
Holden Web LLC                     www.holdenweb.com
PyCon TX 2006                  www.python.org/pycon/




More information about the Python-list mailing list