[Tutor] modify values for object derived from datetime.datetime

Steven D'Aprano steve at pearwood.info
Fri Dec 16 11:26:23 CET 2011


rail shafigulin wrote:
> i writing some code to do device testing at my work. testing is related to
> date and time, so naturally i decided to create a class that inherits from
> datetime.datetime. main reason is that i need to add, subtract and compare
> datetime objects and datetime.datetime allows me to do that. here is the
> code:
> 
> class LTime(datetime.datetime):
>   TOLERANCE = 10
> 
>   def __new__(self, year, month, day, *args):
>     if year == 0:
>       year = 2000
>     return super().__new__(self, year, month, day, *args)


By convention, the first argument of __new__ is normally spelled as "cls", 
short for class, because the instance hasn't been created yet.


>   def modify(self):
>     self = self.replace(2012, 12, 12)
>     print(self)

The replace method creates a new datetime object. Just because you assign it 
to the name "self" doesn't mean you can change the existing datetime object. 
That is simply impossible: datetime objects are immutable, like ints.

You might not quite understand why modifying immutable objects would be bad 
(which is why Python doesn't allow it). I can simulate the effect with this 
simple wrapper class:

 >>> class Mutable:
...     def __init__(self, value):
...             self.value = value
...     def __str__(self):
...             return str(self.value)
...     __repr__ = __str__
...     def add(self, value):
...             self.value += value
...
 >>> one = Mutable(1)  # Pretend this is the int 1
 >>> print(one)
1
 >>> x = one
 >>> x.set(1)  # pretend this was x += 1
 >>> one  # the int 1 has been modified in place
2

So if ints (and datetime objects) could be changed in place, you could never 
be sure what value a literal like 1 would have.

Obviously this is useful in some situations, which is why we have mutable 
objects like lists. But datetime objects are not mutable, a design choice made 
by the creator of the module, so you cannot change it.

So you have to change your design. Instead of writing code like this:


today = LTime(2011, 12, 16)
# ...
# ... do stuff with today
# ...
today.modify(day=17)  # fast forward in time to tomorrow
# ...
# ... do stuff with today, which is actually tomorrow
# ...

you need to change your code to be more like this:


today = LTime(2011, 12, 16)
# ...
# ... do stuff with today
# ...
tomorrow = today.modify(day=17)
# ...
# ... do stuff with tomorrow
# ...




-- 
Steven


More information about the Tutor mailing list