Search code examples
pythonderived-classclass-methodclass-variables

How to properly access and set class variables in a derived class?


Supposed that you have a python class (say B) that is a derived class of some other class (say A) and that class A has both class variables and @classmethods that help you change or view these class variables. I had assumed that a @classmethod in class A that sets a class A class variable using the syntax cls.variable_name = value would work.

This seems to work sometimes but not always which confuses me. Below is an example that does not set the class variables as I would expect. Therefore I cannot tell what cls.something will be accessing and so I have to use A.something which seems that I will be missing the capabilities of cls.something in @classmethods. What does cls.something actually access in class methods and why does the following example not set the test class class variables?

The following example with output hopefully demonstrates what I mean:

class Test():
    epf = 'A'

    @classmethod
    def set_formats(cls, p):
        cls.epf = p

    @classmethod
    def form(cls):
        return cls.epf

class Mytest(Test):
        pass

Here is the output:

>>>c=Mytest
>>>Test.form()
'A'

>>>c.set_formats(p='a')
>>>Test.epf
'A'

>>>c.form()
'a'

>>>c.epf
'a'

So in this example the classmethods are not changing the class variable as I would expect and instead an instance variable seems to appear. If I do the above without a derived class then it works as expected. Hmm? Clearly missing something here!

Now if I change the c.set_formats(p='a', f='A') to Test.set_formats(p='a', f='A') it does work. Is it because c.set_formats uses the class method with cls being an instance?

Edit: Made the code much smaller and changed conventions as requested.


Solution

  • Is it because c.set_formats uses the class method with cls being an instance?

    Yes, you can check via print calls showing the ids of the involved objects.