glamredhel
glamredhel

Reputation: 336

Inheriting from a class (datetime.date) causes a super().__init__(...) too many arguments TypeError

I am using Python 3.6 and wanted to write a class that extends datatime.date and introduces some additional attributes and methods that I need in my code. The problem is that the initialization does not seem to work properly due to seemingly too many arguments.

Below is the code cut down to the minimum:

FORMAT__DD_MM_YYYY = "dd.mm.yyyy"
from datetime import date


class DateExtended(date):
    date_string = None
    date_format = None

    def __init__(self, year: int, month: int, day: int, date_format: str=None):
        super().__init__(year=year, month=month, day=day)
        self.date_format = date_format
        self.date_string = "{:02d}.{:02d}.{:04d}".format(self.day, self.month, self.year)

bla1 = DateExtended(year=2010, month=5, day=3, date_format=FORMAT__DD_MM_YYYY_DOT)

Executing it causes the following error:

bla1 = DateExtended(year=2010, month=5, day=3, date_format=FORMAT__DD_MM_YYYY_DOT)
TypeError: function takes at most 3 arguments (4 given)

What am I doing wrong here and how should that be fixed?

Is it because the date is not extending object?


Side-note: When trying to fix this myself, I have also written a different class which does not inherit from date but just creates a date object and stores it as one of its attributes:

self.date = date(year=year, month=month, day=day)

There no problems are encountered.

Upvotes: 3

Views: 2771

Answers (1)

MSeifert
MSeifert

Reputation: 152647

It's because datetime.date does the initialization in __new__, not in __init__ and the error comes from the fact that datetime.date.__new__ only takes 3 arguments, not 4.

So you have to override __new__ as well:

FORMAT__DD_MM_YYYY = "dd.mm.yyyy"
from datetime import date


class DateExtended(date):
    date_string = None
    date_format = None

    def __new__(cls, year: int, month: int, day: int, date_format: str=None):
        # because __new__ creates the instance you need to pass the arguments
        # to the superclass here and **not** in the __init__
        return super().__new__(cls, year=year, month=month, day=day)

    def __init__(self, year: int, month: int, day: int, date_format: str=None):
        # datetime.date.__init__ is just object.__init__ so it takes no arguments.
        super().__init__()  
        self.date_format = date_format
        self.date_string = "{:02d}.{:02d}.{:04d}".format(self.day, self.month, self.year)

bla1 = DateExtended(year=2010, month=5, day=3, date_format=FORMAT__DD_MM_YYYY)

Upvotes: 4

Related Questions