Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inherit and extend class attributes in Python?

I've made a lot of research on the net but I didn't find the correct way to extend "class" attributes dictionary with new values in a subclass. Most of the documentation are extending attributes inside methods.

I tried dictionary.update() but it doesn't work.

This is my example:

class Super(object):
    dictionary = {'one':1, 'two':2}

    def __init__(self, var):
        self.var = var

    def supermethod(self):
        pass

And I extended it to:

class Subclass(Super):
    dictionary.update({"zero":0})

    def __init__(self, var):
        super(Subclass, self).__init__(var)
        self.var = var

    def submethod(self):
        pass

If I override dictionary - it works fine. But If I try to extend, it gives me:

AttributeError: 'Subclass' object has no attribute 'dictionary'

like image 694
Claudiu Avatar asked Jul 13 '18 11:07

Claudiu


2 Answers

In Python, class is an executable statement. When the interpreter finds a class statement, then first all the code in the class statement block is executed (in a special namespace), then all names defined in that block are used to build the class object (Python classes are objects), and finally the class name is bound to the class object in the current scope.

IOW, within the class statement's block, the class object doesn't exist yet and as a consequence it cannot be referenced, neither explicitly (by the class name) nor implicitly (Python overly flavors explicit over implicit anyway).

OTHO, the parent class object does exists at this point obviously (else you could not inherit from it), so you can explicitly reference it:

class Parent(object):
   attr = something()


class Child(Parent):
   attr = Parent.attr
   # do something with Parent.attr

Note that attributes defined in the class statement block (here attr) are "class attributes", IOW attributes of the class object, and as such are shared amongst instances. When this attribute is a mutable object, mutating it from one instance will affect all instances.

Also remember that Python never implicitly copy anything, so the code below:

class Parent(object):
   attr = {"foo": "bar"}


class Child(Parent):
   attr = Parent.attr
   attr["baaz"] = "quux"
   # or attr.update(baaz="quux") etc

WILL update Parent.attr.

like image 188
bruno desthuilliers Avatar answered Oct 02 '22 14:10

bruno desthuilliers


Subclasses never have their superclasses' attributes as their attributes, whether methods or not.

class Subclass(Super):
  dictionary = Super.dictionary
  dictionary.update({zero:0})
like image 38
Ignacio Vazquez-Abrams Avatar answered Oct 02 '22 13:10

Ignacio Vazquez-Abrams