You've run into what is called a class method.
There's a few ways of figuring this out by looking at the code:
First off, is datetime.datetime.now()
really an instance? if you were to type datetime.datetime
in an interpreter, this is what you would get:
>>> datetime.datetime
<type 'datetime.datetime'>
Datetime is a class. To instantiate it, you'd want to call it:
>>> datetime.datetime(2017, 7, 16, 1, 1, 47)
datetime.datetime(2017, 7, 16, 1, 1, 47)
The ()
brackets with arguments create an instance of the class. But when we call this now()
method, there aren't any brackets!
>>> datetime.datetime.now()
datetime.datetime(2017, 7, 16, 1, 3, 30, 501644)
That's because now()
is a class method. In other words, we don't require an instance of the class to call it.
If you're familiar with class instances and class definitions, you may have written this before:
class Hello(object):
def say_message(self, message):
print(message)
See that handy little self
argument that comes first in that method? self
refers to the instance of the class that is passed down. That's called an instance method. A class method doesn't give us an instance, but rather the class definition. So it doesn't require an instance.
Class methods are much more useful when you're doing advanced things with inheritance and shortcut initializations.
Class methods are usually defined with a decorator:
@classmethod
def now(cls):
...
This is actually the same as writing this:
def now(cls):
...
now = classmethod(now)
Decorators were introduced as part of PEP 318 and brought into the language in Python 2.4. Before decorators were introduced, the second method above was always used. That's because decorators are functions. The @
syntax is just to make this "decoration" more readable and clear. I would read the PEP, since it has a whole bunch of good information on how and why decorators were introduced to the language. In the datetime.now
case, you can see that the second method was used to transform the method into a class method (they do this with all the class methods, including other methods like fromtimestamp
:
def now(cls, tz=None):
"Construct a datetime from time.time() and optional time zone info."
t = _time.time()
return cls.fromtimestamp(t, tz)
now = classmethod(now)