sub-classing the types in the builtin module datetime
attn.steven.kuo at gmail.com
attn.steven.kuo at gmail.com
Thu Aug 16 15:58:49 EDT 2007
On Aug 15, 5:54 pm, "Colin J. Williams" <c... at sympatico.ca> wrote:
> I posted this about 5 hours ago, but it seems to have gone astray.
(snipped)
> >
> >> I wish to sub-class (if that's the right word) datetime and to use a
> >> different signature for the constructor.
> >>
> >> The second part has gone smoothly, but it is difficult to access the
> >> type's methods from the sub-class instance.
> >>
> >> I'm beginning to wonder whether it might might be simpler to write my
> >> own Date class.
> >>
> >> Does anyone have any comments please?
> >>
> >> Colin W.
(snipped)
> Yes, I should have posted an example, but I thought that others might
> have experienced the problem.
>
> It is illustrated at the bottom of this script:
>
> # subClassing.py
>
> import datetime
> import new
> import sys
> import types
>
> class Date(datetime.datetime):
> ''' Date(s) -> a date object.__class__
> where s is an 8 digit string'''
>
> def __new__(cls, YYmmdd):
> ''' YYmmdd is a string, in the form yyyymmdd i.e. 8 digits.
> or a 3-tuple of integers in the form (y, m, d)
> or a 6-tuple of integers in the form (y, m, d, h, m,
> s) '''
(snipped)
>
> a= datetime.datetime(2007, 7, 31)
> d= Date('20070731')
> tm= datetime.time(1, 2)
> try:
> print a.today()
> # print d.today() # grief
> print a.now()
> # print d.now() # grief
> print a.combine(a, tm) # OK, but why not a.combine(tm)?
> # e= d.combine(d, tm) # grief
> print a.utcnow()
> # print d.utcnow() # grief
> print a.ctime()
> print d.ctime()
> except:
> print 'Grief'
> print sys.exc_info()
>
> Colin W.
This problem arises when you change the function signature of __new__.
I'm a little unclear as to why but it seems for the classmethods
(thosed marked with the METH_CLASS flag in the C source code), you
need to arrange to bypass the normal method resolution (I used a
metaclass
to do this):
import datetime
class Date(datetime.datetime):
pass
class FixClassMethods(type):
def __init__(cls, classname, bases, classdict):
# add strptime if using Python 2.5
flagged_as_meth_class = ('today', 'now', 'fromtimestamp',
'fromordinal', 'now', 'utcnow', 'utcfromtimestamp', 'combine')
for meth in flagged_as_meth_class:
setattr(cls, meth, getattr(datetime.datetime, meth))
class DateChangesNewSignature(datetime.datetime):
@staticmethod
def str2ymd(strval):
yyyy, mm, dd = (int(substr) for substr in (strval[:4],
strval[4:6], strval[6:]))
return yyyy, mm, dd
def __new__(cls, strval):
yyyy, mm, dd = DateChangesNewSignature.str2ymd(strval)
return super(DateChangesNewSignature,cls).__new__(cls, yyyy,
mm,
dd)
def __init__(self, strval):
yyyy, mm, dd = DateChangesNewSignature.str2ymd(strval)
super(DateChangesNewSignature, self).__init__(yyyy, mm,
dd)
class DLast(DateChangesNewSignature):
__metaclass__ = FixClassMethods
f = Date(2007,07,07)
print f
print f.today()
f2 = DateChangesNewSignature("20070707")
print f2
try:
print f2.today()
except TypeError, e:
print str(e)
print "Uh?"
f3 = DLast("20070707")
print f3
print f3.today()
I get:
2007-07-07 00:00:00
2007-08-16 12:57:41.480679
2007-07-07 00:00:00
__new__() takes exactly 2 arguments (9 given)
Uh?
2007-07-07 00:00:00
2007-08-16 12:57:41.483104
--
Hope this helps,
Steven
More information about the Python-list
mailing list