pythonclassoopinheritancemagic-methods

Using parent class `__new__` or `__init__` method to assign default attributes for every object/instance of a sub-class


I am trying to create a parent class - Car that would be able to automatically assign a unique id (using uuid.uuid4()), a created_at attribute and an updated_at attribute (both using the datetime and dateutil modules) to any object that would be created through the sub-classes of my parent class.

For example: When an object (honda_civic()) of my sub-class Honda, which inherits from my Car parent class, is created, honda_civic would be automatically assigned a unique id, then it will also have a time created and time updated, as well as the other attributes and methods defined in the Honda sub-class.

Based on my research so far, I know that I would need to define these attributes inside either of the __new__ or __init__ methods of my parent class Car (I stand to be corrected). However, I'm struggling to figure out exactly which of them should have the definitions.

I know that the __new__ method controls object creation while the __init__ method controls object instantiation. My confusion now is that if I define the attributes under the __init__ method, would that not mean that each time the object is created the attributes would have to be passed as arguments? (which is definitely not ideal). What I need help with now is figuring out the syntax of defining the attributes under the __new__ method because I am a bit confused by the def __new__(cls, *args, **kwargs) prototype definition of the __new__ method and how it can accommodate the definitions; can I pass the attributes to the __new__ prototype? like so: def __new__(cls, id, created_at, updated_at)


Solution

  • I think you are overcomplicating this. Car.__init__ should perform initialization that is common to any Car, regardless of the specific subclass used to instantiated the object.

    class Car:
       def __init__(self):
           self.id = uuid.uuid4()
           now = datetime.datetime.now()
           self.created_at = now
           self.modified_at = now
    

    Each subclass will define an __init__ method that first calls its inherited __init__ method, then does any subclass-specific intialization.

    class Honda(Car):
        def __init__(self):
            super().__init__()
            self.something_else = ...
            ...
    
    civic = Honda()
    

    civic.id, civic.created_at, and civic.modified_at are defined by Car.__init__; civic.something_else is defined by Honda.__init__.