Intrastellar Explorer
Intrastellar Explorer

Reputation: 2391

Python using child class's class attribute as default parameter without overriding method

While initializing a class, the default arg for a parameter is a constant class attribute.

class SomeClass:
    """Some class."""

    DEFAULT_VAL = 0

    def __init__(self, some_param: int = DEFAULT_VAL):
        print(f"default = {self.DEFAULT_VAL} and some_param = {some_param}.")


some_class = SomeClass()

Prints: default = 0 and some_param = 0.

When I subclass the class, and override the constant class attribute, it doesn't use it as the default parameter.

class SomeChildClass(SomeClass):
    """Some child class."""

    DEFAULT_VAL = 1


some_child_class = SomeChildClass()

Prints: default = 1 and some_param = 0.

Is there some way I can make this work, without explicitly overriding __init__ in the child class?


Research

How to call parent class init with default values from child class?

Question is very similar, yet they override __init__.

Reinitialize parent class attributes during child class definition

Presents a possible solution using a metaclass to specify DEFAULT_VAL via __new__. This solution adds verbosity to SomeClass, which is not half bad. I am wondering if it can be done even simpler though.

Overriding class variables in python

In this answer, it informs me the problem is that DEFAULT_VAL is evaluated when the function __init__ is defined. However, I am not quite sure if using a classmethod is applicable in my use case.

Upvotes: 0

Views: 725

Answers (1)

juanpa.arrivillaga
juanpa.arrivillaga

Reputation: 95873

The problem here is that default values take objects, not variables/attributes. The object is evaluated once when the function is defined. The generic way to solve this in any function is to do something like:

class SomeClass:
    """Some class."""

    DEFAULT_VAL = 0

    def __init__(self, some_param: int = None):
        if some_param is None:
            some_param = self.DEFAULT_VAL
        print(f"default = {self.DEFAULT_VAL} and some_param = {some_param}.")

Upvotes: 2

Related Questions