Reputation: 463
Class Clock:
def __init__(self):
self._hours = 12
self._minutes = 0
self._seconds = 0
def getHours(self):
return self._hours
def getMinutes(self):
return self._minutes
def getSeconds(self):
return self._seconds
def show(self):
print "%d:%02d:%02d" % (self._hours, self._minutes, self._seconds)
I want to add a method to this class called setTime which takes hours, minutes, and seconds as parameters and make appropriate changes to the object’s attributes. The following code makes use of this class and the method setTime.
clk = Clock()
clk.setTime(12, 34, 2)
print clk.getHours()
clk.show()
def setTime(self, hours = 12, minutes = 34, seconds = 2):
self._hours = hours
self._minutes = minutes
self._seconds = seconds
My question is whether my setTime method is correct? Also, how to check whether my function is correct or not?
Upvotes: 0
Views: 10598
Reputation: 56654
class Clock(object):
def __init__(self, hour=12, minute=0, second=0, milTime=False):
super(Clock,self).__init__()
self.hour = hour
self.minute = minute
self.second = second
self.milTime = milTime # 24-hour clock?
@property
def hour(self):
return self._hour if self.milTime else ((self._hour-1) % 12)+1
@hour.setter
def hour(self, hour):
self._hour = hour % 24
@property
def minute(self):
return self._minute
@minute.setter
def minute(self, minute):
self._minute = minute % 60
@property
def second(self):
return self._second
@second.setter
def second(self, second):
self._second = second % 60
@property
def time(self):
return self.hour, self.minute, self.second
@time.setter
def time(self, t):
self.hour, self.minute, self.second = t
def __str__(self):
if self.milTime:
return "{hr:02}:{min:02}:{sec:02}".format(hr=self.hour, min=self.minute, sec=self.second)
else:
ap = ("AM", "PM")[self._hour >= 12]
return "{hr:>2}:{min:02}:{sec:02} {ap}".format(hr=self.hour, min=self.minute, sec=self.second, ap=ap)
then
c = Clock(12, 15, 10)
print c # -> 12:15:10 PM
c.milTime = True
print c # -> 12:15:10
c.hour = 9
print c # -> 09:15:10
c.milTime = False
print c # -> 9:15:10 AM
c.time = 12,34,2
print c # -> 12:34:02 PM
Getters and setters (c.getX() etc) are un-Pythonic; if some translation is needed, use class property methods (as above), otherwise access the properties directly (as with Clock.milTime).
Upvotes: 1
Reputation: 13576
It looks correct to me, except for two things. You might want to remove the default values; they seem unnecessary. You want to range check the values and raise ValueError
if they're out of range.
A simple test would be to set the clock to something, then get the data back and check it; repeat for a few values. This can be automated; the doctest
module is fairly simple to use.
EDIT:
Here's an example of using doctest
. The tests go directly into docstrings anywhere in the module. doctest.testmod()
looks for them and tries to run them as if they were interactive sessions. If the output isn't as expected, it says so. If all goes well, there's no output.
class Clock:
"""Clock
Class that acts like a clock.
For doctest -
>>> c = Clock()
>>> c.setTime(23, 59, 59)
>>> c.show()
23:59:59
>>> c.getMinutes()
59
>>> c.setTime(0, 0, 0)
>>> c.show()
0:00:00
# No range or type checking yet
>>> c.setTime(42, 'foo', [1, 2, 3])
# However, the print will fail
>>> c.show()
Traceback (most recent call last):
...
TypeError: int argument required
# Another kind of error
>>> c.setTime(foo=42)
Traceback (most recent call last):
...
TypeError: setTime() got an unexpected keyword argument 'foo'
"""
def __init__(self):
self._hours = 12
self._minutes = 0
self._seconds = 0
def getHours(self):
return self._hours
def getMinutes(self):
return self._minutes
def getSeconds(self):
return self._seconds
def show(self):
print "%d:%02d:%02d" % (self._hours, self._minutes, self._seconds)
def setTime(self, hours = 12, minutes = 34, seconds = 2):
self._hours = hours
self._minutes = minutes
self._seconds = seconds
if __name__ == '__main__':
import doctest
doctest.testmod()
Upvotes: 3
Reputation: 98776
Your setTime
method is correct, however it seems odd to be setting the default hours, minutes, and seconds to such arbitrary numbers. Perhaps hours = 12, minutes = 0, and seconds = 0 would make more sense? Perhaps even doing away with the default values altogether is best.
You don't have any validation -- what if someone uses your class and accidentally sets the hours to 29?
Finally, as I mentioned in my comment, you can test your function by trying it out. Does it do the right thing in the simple case? Does it do the right thing with default values? What happens if you toss in negative seconds? What do you want to happen? These are all things you should consider when testing a method or class -- does it work in the intended case, and does it work in all the exceptional/corner cases.
For your example, you could write a simple unit test like this, using asserts:
def testSetTime():
clock = Clock()
clock.setTime(2, 18, 36)
assert clock.getHours() == 2
assert clock.getMinutes() == 18
assert clock.getSeconds() == 36
Then you can add more tests as needed (note that each unit test should test only one thing).
Upvotes: 1
Reputation: 45295
You can initialize the time in the class constructor:
Class Clock:
def __init__(self, hours, minutes, seconds):
self._hours = hours
self._minutes = minutes
self._seconds = seconds
....
clk = Clock(12, 34, 2)
Upvotes: 4