Hi everyone,
I'd like to create a child class to the date class in the datetime module and, apart from adding some new methods to it, I'd like my child class to be initializable through different argument arrangements.

For example, beyond the (year, month, day) initialization arguments of the parent, I'd like the child class to be also initializable through a string, say, '1Jan2009', where the __init__ () method of the child is called with *args and depending on the arguments it resolves what (year, month, day) list it should use to initialize the parent, something like:

class DatePlus(date):
    def __init__(self, *args):
        if len(args) == 3:
            (y, m, d) = args
        elif len(args) == 1 and type(args[0]) == type(''):
            (y, m, d) = self.translate_string(self, arg[0])
        date.__init__(self, y, m, d)

However, I can't seem to be able to initialize the child class with a single argument; I get a TypeError that 3 arguments are required, 1 given.

Is there a way to accomplish what I'm trying to do or should the child class always be called with the same argument list structure as the parent?

Many thanks and have a happy new year.

Dani AI

Generated

The TypeError happens because datetime.date is an immutable built-in type whose actual object construction (and argument checking) happens in new, not in init. Overriding init will not change the signature that the interpreter enforces when creating the object. As observed, calling the subclass with a single string triggers the base-type constructor before the subclass init runs; as suggested, calling the parent is correct for delegation, but that alone doesn't avoid the error.

A practical fix is to override new in the subclass, parse the flexible arguments there, and return an instance created by the base class new. Example approach:

from datetime import date, datetime

class DatePlus(date):
    def __new__(cls, *args, **kwargs):
        if len(args) == 1 and isinstance(args[0], str):
            # parse '1Jan2009' using strptime and convert to a date
            dt = datetime.strptime(args[0], '%d%b%Y')
            return super(DatePlus, cls).__new__(cls, dt.year, dt.month, dt.day)
        if len(args) == 3:
            return super(DatePlus, cls).__new__(cls, args[0], args[1], args[2])
        return super(DatePlus, cls).__new__(cls, *args, **kwargs)

Alternative: provide explicit alternate constructors such as @classmethod def fromstring(cls, s): ... and call DatePlus.fromstring('1Jan2009'). This keeps the normal constructor identical to the base class and avoids subtleties with built-in types.

Notes and cautions:

  • Month names from %b are locale-dependent; choose parsing accordingly.
  • Always return the result of the base __new__ call. For modern Python 3 code, super().__new__(cls, ...) can be used.
  • Official references: Python data model on __new__ and the date docs (object.new, datetime.date, strptime).

Nowadays you should do : super(DatePlus, self).__init__(y,m,d) I think. Instead of explicitly calling __init__

Also change this: (y, m, d) = self.translate_string(self, arg[0]) to this: (y, m, d) = self.translate_string(arg[0]) Also, type('') can be replaced with str

Thanks, jcao219.

Still, even if I use super, I think the fact alone that the parent and child classes have mismatching argument lists in their initialization causes the TypeError I'm straggling with.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.