Overloading ctor doesn't work?

  • Thread starter =?ISO-8859-1?Q?Martin_H=E4cker?=
  • Start date
?

=?ISO-8859-1?Q?Martin_H=E4cker?=

Hi there,

I just tried to run this code and failed miserably - though I dunno why.
Could any of you please enlighten me why this doesn't work?

Thanks a bunch.

--- snip ---
import unittest
from datetime import datetime

class time (datetime):
def __init__(self, hours=0, minutes=0, seconds=0, microseconds=0):
print "blah"
datetime.__init__(self, 1, 1, 1, hours, \
minutes, seconds, microseconds)


class Test (unittest.TestCase):
def testSmoke(self):
# print time() # bombs, and complains that
# the time ctor needs at least 3 arguments
self.assertEquals(datetime(1,1,1,1,2,3,4),time(1,2,3,4))


if __name__ == '__main__':
unittest.main()
--- snap ---

The reason I want to do this is that I want to work with times but I
want to do arithmetic with them. Therefore I cannot use the provided
time directly.

Now I thought, just overide the ctor of datetime so that year, month and
day are static and everything should work as far as I need it.

That is, it could work - though I seem to be unable to overide the ctor. :(

Why is that?

cu Martin
 
S

Steve Holden

Martin said:
Hi there,

I just tried to run this code and failed miserably - though I dunno why.
Could any of you please enlighten me why this doesn't work?

Thanks a bunch.

--- snip ---
import unittest
from datetime import datetime

class time (datetime):
def __init__(self, hours=0, minutes=0, seconds=0, microseconds=0):
print "blah"
datetime.__init__(self, 1, 1, 1, hours, \
minutes, seconds, microseconds)


class Test (unittest.TestCase):
def testSmoke(self):
# print time() # bombs, and complains that
# the time ctor needs at least 3 arguments
self.assertEquals(datetime(1,1,1,1,2,3,4),time(1,2,3,4))


if __name__ == '__main__':
unittest.main()
--- snap ---

The reason I want to do this is that I want to work with times but I
want to do arithmetic with them. Therefore I cannot use the provided
time directly.

Now I thought, just overide the ctor of datetime so that year, month and
day are static and everything should work as far as I need it.

That is, it could work - though I seem to be unable to overide the ctor. :(

Why is that?
Perhpas the error message or output, which you don't provide, would
avoid our having to use our psychic powers? ;-)

In other words: what's wrong? How do you *know* you can't override it?

regards
Steve
 
K

Kent Johnson

Here is a simpler test case. I'm mystified too:

from datetime import datetime

class time (datetime):
def __init__(self, hours=0, minutes=0, seconds=0, microseconds=0):
datetime.__init__(self, 2001, 10, 31, hours, minutes, seconds, microseconds)

print time(1,2,3,4) # => 0001-02-03 04:00:00
print time() # => TypeError: function takes at least 3 arguments (0 given)


What happens to the default arguments to time.__init__? What happens to the 2001, 10, 31 arguments
to datetime.__init__?

I would expect the output to be
2001-10-31 01:02:03.000004
2001-10-31 00:00:00.000000

Kent
 
F

Francis Girard

Hi,

It looks like the assertEquals use the != operator which had not been defined
to compare instances of your time class and instances of the datetime class.
In such a case, the operator ends up in comparing the references to instances,
i.e. the "id" of the objects, i.e. their physical memory addresses, which of
course can't be the same. And that is why your test fails.

Consider defining the __cmp__ method (see 2.3.3 Comparisons of the library
reference). Sess also the operator module.

Francis Girard
LANNILIS
Breizh
FRANCE

Le jeudi 20 Janvier 2005 19:23, Martin Häcker a écrit :
 
F

Francis Girard

Wow !
Now, this is serious. I tried all sort of things but can't solve the problem.
I'm mystified too and forget my last reply.
I'm curious to see the answers.
Francis Girard
Le jeudi 20 Janvier 2005 19:59, Kent Johnson a écrit :
 
P

Paul McGuire

Kent Johnson said:
Here is a simpler test case. I'm mystified too:

from datetime import datetime

class time (datetime):
def __init__(self, hours=0, minutes=0, seconds=0, microseconds=0):
datetime.__init__(self, 2001, 10, 31, hours, minutes, seconds, microseconds)

print time(1,2,3,4) # => 0001-02-03 04:00:00
print time() # => TypeError: function takes at least 3 arguments (0 given)


What happens to the default arguments to time.__init__? What happens to the 2001, 10, 31 arguments
to datetime.__init__?

I would expect the output to be
2001-10-31 01:02:03.000004
2001-10-31 00:00:00.000000

Kent

I can't explain this behavior, but this version does work (uses
datetime.combine instead of ctor)

-- Paul


from datetime import datetime, date as dt_date, time as dt_time

class time_d (datetime):
def __new__(cls, *args):
# default to no microseconds
if len(args)==3:
args = args + (0,)
if len(args)==4:
tmpdate = datetime.today()
h, mi, s, ms = args
return datetime.combine(tmpdate, dt_time(h,mi,s,ms))
elif len(args)==7:
y,m,d,h,mi,s,ms = args
return datetime.combine(dt_date(y,m,d), dt_time(h,mi,s,ms))
else:
raise TypeError, "wrong number of args"

print time_d(2001,10,31,1,2,3,4)
print time_d(1,2,3,4)
print time_d(1,2,3)
 
K

Kent Johnson

Paul said:
the 2001, 10, 31 arguments



I can't explain this behavior, but this version does work (uses
datetime.combine instead of ctor)

-- Paul


from datetime import datetime, date as dt_date, time as dt_time

class time_d (datetime):
def __new__(cls, *args):
# default to no microseconds
if len(args)==3:
args = args + (0,)
if len(args)==4:
tmpdate = datetime.today()
h, mi, s, ms = args
return datetime.combine(tmpdate, dt_time(h,mi,s,ms))
elif len(args)==7:
y,m,d,h,mi,s,ms = args
return datetime.combine(dt_date(y,m,d), dt_time(h,mi,s,ms))
else:
raise TypeError, "wrong number of args"

print time_d(2001,10,31,1,2,3,4)
print time_d(1,2,3,4)
print time_d(1,2,3)


Ah, right. The light turns on...

datetime is immutable so overriding the constructor doesn't change the constructed object. You have
to override __new__ instead.
http://www.python.org/2.2.1/descrintro.html#__new__

This works:

from datetime import datetime

class time (datetime):
def __new__(cls, hours=0, minutes=0, seconds=0, microseconds=0):
return datetime.__new__(cls, 2001, 10, 31, hours, minutes, seconds, microseconds)

print time(1,2,3,4) # => 2001-10-31 01:02:03.000004
print time() # => 2001-10-31 00:00:00

Kent
 
N

Nick Craig-Wood

Martin Häcker said:
Now I thought, just overide the ctor of datetime so that year, month and
day are static and everything should work as far as I need it.

That is, it could work - though I seem to be unable to overide the ctor. :(

Why is that?

Its a bug!

http://sourceforge.net/tracker/index.php?func=detail&aid=720908&group_id=5470&atid=105470

However its been fixed in a recent Python 2.3.

(I was bitten by the same thing which used to fail but now works after
an upgrade of python 2.3!)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top