Subclassing datetime: is there a better way to save the resulting type of an object after arithmetic operations?

I recently came across a situation where I needed to subclass datetime.datetime and datetime.timedelta in order to add several methods. I immediately found that any arithmetic operations returned a datetime.datetime object when I expected it to return an instance of mydatetime.mydatetime . Below is the solution that the employee helped me deal with this problem. Does anyone have a shorter or more convenient suggestion? Are there any dangers for what I did here? Did I miss something important?

 from datetime import datetime, timedelta def _to_mydatetime(native): '''Instantiates object of appropriate class based on class of the input object.''' if hasattr(native, 'timetuple'): return mydatetime(*native.timetuple()[:6]) else: return mytimedelta(native.days, native.seconds) class mydatetime(datetime): '''Subclass of datetime''' def __add__(self, other): result = super(mydatetime, self).__add__(other) return _to_mydatetime(result) def __sub__(self, other): result = super(mydatetime, self).__sub__(other) return _to_mydatetime(result) class mytimedelta(timedelta): def __add__(self, other): result = super(mytimedelta, self).__add__(other) return _to_mydatetime(result) def __sub__(self, other): result = super(mytimedelta, self).__sub__(other) return _to_mydatetime(result) def __div__(self, other): result = super(mytimedelta, self).__div__(other) return _to_mydatetime(result) def __rmul__(self, other): result = super(mytimedelta, self).__rmul__(other) return _to_mydatetime(result) def __mul__(self, other): result = super(mytimedelta, self).__mul__(other) return _to_mydatetime(result) 
+4
source share
1 answer

Well, this is the right way to do this (I would just split the converter method into two). Python helps reduce code duplication:

 from datetime import * def convproxy(methods,converter): def f(cls): def _proxyfactory(method): def _convproxy(self,*args,**kwargs): return converter(getattr(super(cls,self),method)(*args,**kwargs)) return _convproxy for m in methods: setattr(cls,m,_proxyfactory(m)) return cls return f @convproxy(('__add__','__sub__'),lambda d:mydatetime(d.timetuple()[:6])) class mydatetime(datetime): pass @convproxy(('__add__','__sub__','__div__','__rmul__','__mul__'),\ lambda t:mytimetuple(t.days,t.seconds)) class mytimedelta(timedelta): pass 

The hidden code under convproxy is just a smart-aleck way to create the specified methods when creating a class, each of which calls the superclass method and subclasses the result using the specified conversion function.

+1
source

Source: https://habr.com/ru/post/1383538/


All Articles