I'm taking an "intro to object-oriented programming" class and I'm on chapter 17 of Think Python. The following code is stumping me. I keep getting "AttributeError: 'Time' object has no attribute 'print_time'" when running it and I'm having little luck figuring it out. Can someone help break down what I'm doing wrong and help explain it a little better for me?
class Time(object):
"""represents the time of day. attributes: hour, minute, second"""
def print_time(time):
print '%.2d:%.2d:%.2d' % (time.hour, time.minute, time.second)
start = Time()
start.hour = 9
start.minute = 45
start.second = 00
print_time(start)
class Time(object):
def print_time(time):
print '%.2d:%.2d:%.2d' % (time.hour, time.minute, time.second)
start.print_time()
I read that it was an indentation error but I have IDLE set to warn me for conflicts and have checked it twice to no avail.
Let's go through your code a step at a (cough) time.
class Time(object):
"""represents the time of day. attributes: hour, minute, second"""
Here, you're defining a class Time
. It has a docstring, but no methods or other attributes.
def print_time(time):
print '%.2d:%.2d:%.2d' % (time.hour, time.minute, time.second)
This is a function, completely separate from the Time
class you defined earlier, which accepts an argument time
and tries to print a string using time
's hour
, minute
and second
attributes. If time
doesn't have all of those attributes, you'll get an error.
start = Time()
This creates a Time
object called start
.
start.hour = 9
start.minute = 45
start.second = 00
These lines add hour
, minute
and second
attributes to start
.
print_time(start)
This calls print_time
with start
as an argument, resulting in the output:
09:45:00
So far so good. Now ...
class Time(object):
def print_time(time):
print '%.2d:%.2d:%.2d' % (time.hour, time.minute, time.second)
This creates a new class, which happens to also be called Time
. It doesn't have a docstring this time, but it does have a method called print_time
(which is completely separate from the print_time
function defined earlier, although it has the same name and code).
It's important to realise at this point that just because you've created a new class called Time
, that doesn't have any effect at all on objects you created with the previously defined class. They're still instances of the original Time
class you defined. It's easy to prove this with the builtin help
function:
>>> help(start)
Help on Time in module __main__ object:
class Time(__builtin__.object)
| represents the time of day. attributes: hour, minute, second
|
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
start.print_time()
Notice that help
shows you the docstring from the original Time
class, but not the method from the new version.
>>> help(Time)
Help on class Time in module __main__:
class Time(__builtin__.object)
| Methods defined here:
|
| print_time(time)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
... whereas this shows the print_time
method from the new Time
class, but not the docstring from the original one.
One way to think of this is that a class is like a factory that makes objects – and tearing down the Ford factory then building a new one in the same place doesn't have any effect on the '71 Mustang already sitting in your driveway.
If you want an instance of the new Time
class, you'll have to create it:
>>> restart = Time()
... and then, once it has the right attributes ...
>>> restart.hour = 9
>>> restart.minute = 45
>>> restart.second = 00
... you'll be able to call its print_time
method successfully:
>>> restart.print_time()
09:45:00