Why does __init__ not get called?

Discussion in 'Python' started by Rob Conner, Aug 8, 2005.

  1. Rob Conner

    Rob Conner Guest

    I'm still working on my DateTime class from last week...
    Why does __init__ not get called?

    The docs at
    http://www.python.org/dev/doc/devel/ref/customization.html
    read "If __new__() returns an instance of cls, then the new instance's
    __init__() method will be invoked" and as far as I can tell cls is very
    much an instance of DateTime

    ************
    import datetime
    _datetime = datetime.datetime

    class DateTime(_datetime):
    """
    Identical to builtin datetime.datetime, except it accepts
    invalid dates and times as input.
    """
    _valid = True
    __dict__ = _datetime.__dict__

    def __init__(self, year, month, day, *args, **kw):
    print "init called"
    _valid = False
    self.year = year
    self.month = month
    self.day = day
    self.args = args
    self.kw = kw

    def throwError():
    raise ValueError, 'Invalid Date'
    for method in _datetime.__dict__.keys():
    if method!='__doc__':
    setattr(self, method, throwError)


    def __new__(cls, year, month, day, *args, **kw):
    print "new called"
    try:
    return _datetime.__new__(cls, year, month, day, *args,
    **kw)
    except ValueError:
    return cls
    *************
    Rob Conner, Aug 8, 2005
    #1
    1. Advertising

  2. Uh... are you actually trying to instantiate this class?

    mydate = DateTime(2005, 8, 8)

    The reason I ask is that __init__ /is/ called when I run your code on
    Python 2.4, provided that the above line is added to the end.
    Lonnie Princehouse, Aug 8, 2005
    #2
    1. Advertising

  3. Rob Conner

    Rob Conner Guest

    Ah ok, thats interesting I hadn't even tried a valid date yet. Now how
    do I get this thing to call __init__ when I pass in an invalid date and
    the ValueError is thrown and caught within __new__.

    dt = DateTime(2005, 02, 30)
    Rob Conner, Aug 9, 2005
    #3
  4. Rob Conner

    Rob Conner Guest

    Not takers? This is my attempt to get some attention by bumping my own
    post.
    Rob Conner, Aug 9, 2005
    #4
  5. Rob Conner

    infidel Guest

    I think you have to call type.__new__ like this:

    def __new__(cls, year, month, day, *args, **kw):
    print "new called"
    try:
    return _datetime.__new__(cls, year, month, day, *args,
    **kw)
    except ValueError:
    return type.__new__(cls, ...)

    Are you sure you can specify arbitrary arguments to the __new__ method?
    I thought they had to be the class object, the tuple of bases, and the
    dictionary of names.
    infidel, Aug 9, 2005
    #5
  6. Rob Conner

    infidel Guest

    > Are you sure you can specify arbitrary arguments to the __new__ method?
    > I thought they had to be the class object, the tuple of bases, and the
    > dictionary of names.


    Nevermind, I think I was imagining metaclasses rather than just regular
    overriding of __new__
    infidel, Aug 9, 2005
    #6
  7. Rob Conner

    infidel Guest

    This doesn't work. I'm out of my league here.
    infidel, Aug 9, 2005
    #7
  8. What kinds of illegal date values are you trying to represent? The
    reason I ask is that it's not going to be as easy as subclassing
    datetime... datetime is implemented in C. and so enforcement of legal
    values is going to be in the C code. For the time.h functions, you're
    also going to be constrained by the size of the time_t struct, which is
    probably a long int on your platform. See Modules/datetimemodule.c in
    the Python source.

    One thing you could do would be to copy datetimemodule.c and build your
    own C extension type based on it... things like MAXYEAR 9999 could be
    changed that way.

    The other thing would be to write a pure-python datetime class without
    trying to inherit datetime.datetime.
    Lonnie Princehouse, Aug 9, 2005
    #8
  9. Rob Conner

    Rob Conner Guest

    I'm out of my league too. I don't know enough about __new__ and
    __init__.
    I just went another route and did a wrapper for datetime, and didn't
    extend it.
    Thanks for the effort.

    By chance... does anyone know, if I wrote a class, and just wanted to
    override __new__ just for the fun of it. What would __new__ look like
    so that it behaves exactly the same as it does any other time.
    Rob Conner, Aug 10, 2005
    #9
  10. Rob Conner wrote:
    > By chance... does anyone know, if I wrote a class, and just wanted to
    > override __new__ just for the fun of it. What would __new__ look like
    > so that it behaves exactly the same as it does any other time.


    Simple:

    class C(object):
    def __new__(cls, *args, **kwargs):
    return super(C, cls).__new__(cls, *args, **kwargs)

    Basically, you're calling object's __new__ method, which in CPython does
    something like mallocing the appropriate amount of memory, setting the
    __class__ attribute of the object, etc.

    Note that __new__() doesn't call __init__(). Both __new__() and
    __init__() are called individually by the metaclass. For new-style
    classes, "type" is the metaclass, and it's __call__() method looks
    something like:

    def __call__(cls, *args, **kwargs):
    obj = cls.__new__()
    if not isinstance(obj.__class__, cls):
    return obj
    obj.__class__.__init__(obj, *args, **kwargs)
    return obj

    (But see Objects/typeobject.c:409 for the full gory details.)

    STeVe
    Steven Bethard, Aug 11, 2005
    #10
  11. Steven Bethard wrote:
    > def __call__(cls, *args, **kwargs):
    > obj = cls.__new__()
    > if not isinstance(obj.__class__, cls):

    ^^^^^^^^^^
    issubclass

    > return obj
    > obj.__class__.__init__(obj, *args, **kwargs)
    > return obj


    STeVe
    Steven Bethard, Aug 12, 2005
    #11
  12. Rob Conner

    Fuzzyman Guest

    If you subclass strings you have to do your magic in __new__ rather
    than __init__. It receives the same arguments as you would normally
    expect to go to __init__.

    (Except cls rather than self).

    Best Regards,

    Fuzzy
    http://www.voidspace.org.uk/python
    Fuzzyman, Aug 12, 2005
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steven Bethard
    Replies:
    2
    Views:
    455
    Steven Bethard
    Feb 16, 2005
  2. Sriek
    Replies:
    21
    Views:
    934
    Simon Brunning
    May 27, 2005
  3. Kent Johnson
    Replies:
    7
    Views:
    909
    Jan Niklas Fingerle
    Feb 12, 2006
  4. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,816
    Smokey Grindel
    Dec 2, 2006
  5. Ramchandra Apte
    Replies:
    17
    Views:
    336
    Manuel Pégourié-Gonnard
    Sep 30, 2012
Loading...

Share This Page