How to initialise a instance of a class with current time as attribute

Viewed 409

I'm defining a class that has a time attribute which, but default, is set as the current UTC time.

import datetime

class Timer:
    def __init__(self, time = datetime.datetime.utcnow()):
        self.time = time
        print('Instance created at', self.time)
        
        
a = Timer()

The problem is that once defined (or when it is imported, if it's within module), this attribute is set forever! All new instances of the class "inherit" the time from the class, evaluated when it was defined, instead of generating its own "current time" when __init__ is called. Why isn't the function to obtaint current UTC time evaluated every time a new instance is created?

1 Answers

By defining the default kwarg for time, time is evaluated when the class definition object is added/interpreted see function __defaults__, an immutable tuple.

>>> class Timer:
...     def __init__(self, time = datetime.datetime.utcnow()):
...         self.time = time
...         print('Instance created at', self.time)
... 
>>> Timer.__init__.__defaults__
# notice how the date is already set here
(datetime.datetime(2021, 2, 19, 15, 22, 42, 639808),)

Whereas you're looking to evaluate it when the class object instantiates.

>>> class Timer:
...     def __init__(self, time = None):
...         self.time = time or datetime.datetime.utcnow()
...         print('Instance created at', self.time)
... 
>>> Timer.__init__.__defaults__
(None,)
>>> a = Timer()
Instance created at 2021-02-19 15:04:45.946796
>>> b = Timer()
Instance created at 2021-02-19 15:04:48.313514
Related