-2

I am wondering why this works

import datetime as dt

test1 = dt.datetime
print(test)

''' prints: <class 'datetime.datetime'>'''

So as far as I understand python, to create an instance of a class you need to call it with brackets like this:

test2 = dt.datetime(2021, 12, 31)

(Calling the constructor method forces you to put in year, month and day).

At first I thought calling datetime like in the first example (without the brackets) must be an attribute or something. But I can't find a single standing attribute "datetime" in the class "datetime".

And the funny thing is - it doesn't matter how you call it, because both lines lead to the same result:

test = dt.datetime
test2 = dt.datetime(2021, 12, 31)

print(test.now())
print(test2.now())

But why? What did I miss? Thanks a lot!

CodeCannibal
  • 324
  • 6
  • 21
  • 3
    `dt.datetime` is the class `datetime`, not an instance of it. – khelwood Dec 20 '21 at 20:39
  • `dt.datetime` _is_ `datetime.datetime`, because you did `import datetime as dt`. Here the `dt` refers to the module `datetime`. – Pranav Hosangadi Dec 20 '21 at 20:40
  • In this first case you are just printing the class identifier itself, not a method from within the class – itprorh66 Dec 20 '21 at 20:40
  • You can run `dt.datetime.now()` or call `now()` on an instance of `dt.datetime` because instances can access class methods – Pranav Hosangadi Dec 20 '21 at 20:41
  • So, short answer: You're _not_ calling it at all (when you call a class, you get returned an instance; when you don't call it, you still have a reference to the class itself). This question in based on a false premise. – Charles Duffy Dec 20 '21 at 20:43
  • 1
    If you're familiar with opening files, does it surprise you that you can do `print(open)`? You didn't give the function any file to open, but it still prints something! It's not called at all, you're just printing the `__repr__` of the method – roganjosh Dec 20 '21 at 20:43
  • Compare to `import datetime as dt; print(dt.datetime)`. – Charles Duffy Dec 20 '21 at 20:46
  • So that means: dt.datetime is a reference to datetime class, but NOT an instance of it. When calling test.now() it is actually the same as datetime.datetime,now() - which is actually a class method. And this class method will (somehow) create an instance of datetime in the background and give it back to the caller. Correct? – CodeCannibal Dec 20 '21 at 20:52
  • @CodeCannibal as per my answer (which you may or may not have seen), this is not correct. A class method used from the class object (i.e. not an instance) does not create an instance in the background. See references in my answer. – ApplePie Dec 20 '21 at 20:54

1 Answers1

2

A few things to unpack here.

import datetime as dt

This imports the datetime module and aliases it as dt. Next, dt.datetime is the class datetime inside the module dt (alias for datetime module). Finally, now() is defined as a class method so it does not need to be instantiated. Therefore, dt.datetime.now() calls the class method now of class datetime of module dt whereas the following:

date = dt.datetime(2021, 1, 1)
date.now()

Creates an instance of the datetime class and then have it access the class method now.

See the definition the datetime class within the module:

# Excerpt of datetime.py on Python 3.8.10
class datetime(date):
    @classmethod
    def now(cls, tz=None):
        "Construct a datetime from time.time() and optional time zone info."
        t = _time.time()
        return cls.fromtimestamp(t, tz)

Finally, see here what the Python reference has to say on the classmethod decorator:

A class method can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class.

ApplePie
  • 8,814
  • 5
  • 39
  • 60
  • Thanks a lot - that helped me :-) As Charles Duffy wrote: "This question in based on a false premise." . I was too focused on finding an class attribute "datetime" within the class "datetime", that I totally overlooked the fact, that "dt.datetime" is a reference to the class itself and not to an instance. Once again - thank you all for your quick and nice support ! – CodeCannibal Dec 20 '21 at 20:57