Aren’t class attributes inherited?

Question:

I have the following python classes:

parent.py

#! /usr/bin/env python3
class parent():
    CONSTANT = 10

child.py

#! /usr/bin/env python3
from parent import parent

class child(parent):
    print(CONSTANT)
    
    def my_method(self):
        print(CONSTANT)

But child cannot access CONSTANT.

Why doesn’t that work? Is there a way to access the parent’s class attributes (without transforming them all into instance attributes…)

Asked By: Manu

||

Answers:

They are inherited.

class parent:
    CONSTANT = 10

class child(parent):
    pass

print(child.CONSTANT) # 10
Answered By: matszwecja

You should encase your print into classmethod and reference attribute of class rather than global variable, consider following simple example

class Parent:
   CONSTANT = 10
class Child(Parent):
   @classmethod
   def print_constant(cls):
       print(cls.CONSTANT)
Child.print_constant()

gives output

10
Answered By: Daweo

It already inherited that. Test it without that print line(I’ve put both in a module, but that doesn’t matter the error is from something else, I’m gonna talk about it next):

class parent:
    CONSTANT = 10

class child(parent):
    pass

print(child.CONSTANT)  # 10

But why it throws NameError: name 'CONSTANT' is not defined in your example?

class keyword in Python is used to create classes which are instances of type type. In it’s simplified version, it does the following:

  1. Python creates a namespace(an empty dictionary basically) and executes the body of the class in that namespace so that it will be populated with all methods and attributes and so on…

  2. Then calls the three-arguments form of type(). The result of this call is your class which is then assign to a symbol which is the name of your class.

The point is when the body of the class is being executed, it doesn’t know anything about the parent namespace , likewise it doesn’t know what is CONSTANT. So print(CONSTANT) is gonna throw a NameError exception.

regarding your comment: Since you already inherited that value, you can access it through both the instance and the class. both work:

class parent:
    CONSTANT = 10

class child(parent):
    def regular_method(self):
        print(self.CONSTANT)
        print(self.__class__.CONSTANT)
        print(super().CONSTANT)

    @classmethod
    def class_method(cls):
        print(cls.CONSTANT)

obj = child()
obj.regular_method()
obj.class_method()
Answered By: S.B