CodeQL documentation

__init__ method calls overridden method

ID: py/init-calls-subclass
Kind: problem
Severity: warning
Precision: high
Tags:
   - reliability
   - correctness
Query suites:
   - python-security-and-quality.qls

Click to see the query in the CodeQL repository

When an instance of a class is initialized, the super-class state should be fully initialized before it becomes visible to the subclass. Calling methods of the subclass in the superclass’ __init__ method violates this important invariant.

Recommendation

Do not use methods that are subclassed in the construction of an object. For simpler cases move the initialization into the superclass’ __init__ method, preventing it being overridden. Additional initialization of subclass should be done in the __init__ method of the subclass. For more complex cases, it is advisable to use a static method or function to manage object creation.

Alternatively, avoid inheritance altogether using composition instead.

Example

#Superclass __init__ calls subclass method

class Super(object):

    def __init__(self, arg):
        self._state = "Not OK"
        self.set_up(arg)
        self._state = "OK"

    def set_up(self, arg):
        "Do some set up"

class Sub(Super):

    def __init__(self, arg):
        Super.__init__(self, arg)
        self.important_state = "OK"

    def set_up(self, arg):
        Super.set_up(self, arg)
        "Do some more set up" # Dangerous as self._state is "Not OK"


#Improved version with inheritance:

class Super(object):

    def __init__(self, arg):
        self._state = "Not OK"
        self.super_set_up(arg)
        self._state = "OK"

    def super_set_up(self, arg):
        "Do some set up"


class Sub(Super):

    def __init__(self, arg):
        Super.__init__(self, arg)
        self.sub_set_up(self, arg)
        self.important_state = "OK"


    def sub_set_up(self, arg):
        "Do some more set up"


References