我正在学习使用python如何像计算机科学家一样思考:学习python 3.
我正在学习OOP并整理了一些代码来回答书中的问题,但我觉得我应该做其他的事情。
有问题的代码是incremental()
,其目标是增加对象的值。现在我的最终解决方案是让我的方法成为初始化方法的副本,然后在那里添加时间。
这感觉很草率:
class MyTime:
def __init__(self, hrs=0, mins=0, secs=0,):
""" Create a new MyTime object initialized to hrs, mins, secs.
The values of mins and secs may be outside the range 0-59,
but the resulting MyTime object will be normalized.
"""
# calculate total seconds to represent
totalsecs = hrs*3600 + mins*60 + secs
self.hours = totalsecs // 3600 # split in h, m, s
leftoversecs = totalsecs % 3600
self.minutes = leftoversecs // 60
self.seconds = leftoversecs % 60
def incerment(self,t):
# increase the time by t amount
totalsecs = self.hours * 3600 + self.minutes * 60 + self.seconds + t
self.hours = totalsecs // 3600 # split in h, m, s
leftoversecs = totalsecs % 3600
self.minutes = leftoversecs // 60
self.seconds = leftoversecs % 60
t1 = MyTime(5,5,5)
t2 = MyTime(10,10,10)
t3 = MyTime(12,12,12)
print('before:',t1)
t1.incerment(100)
print('after:',t1)
那怎么样? 有没有办法清理它?
答案 0 :(得分:4)
感觉就像你应该做的其他事情因为hours
,minutes
,seconds
是属性。
您不需要将这些值存储为对象的属性,只是希望能够在需要时访问这些值。
调用类似的内容:
>>> t1.hours
5
所以,让我们用property
重写你的例子:
class MyTime:
def __init__(self, hrs=0, mins=0, secs=0):
self.totalsecs = hrs*3600 + mins*60 + secs
@property
def hours(self):
return self.totalsecs // 3600
@property
def minutes(self):
return self._get_leftoversecs() // 60
@property
def seconds(self):
return self._get_leftoversecs() % 60
def _get_leftoversecs(self):
return self.totalsecs % 3600
def increment(self, t):
self.totalsecs += t
用法示例:
>>> t1 = MyTime(5,5,5)
>>> t1.hours
5
>>> t1.hours()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
>>> t1.seconds
5
>>> t1.totalsecs
18305
>>> t1.increment(10)
>>> t1.seconds
15
>>> t1.totalsecs
18315
我不知道您是否注意到了您实际上不再需要increment
功能:
>>> t1.totalsecs += 10
>>> t1.totalsecs
18325
我知道property
必须比你正在做的要先进一点,但我认为这值得一个例子。
修改:Lattyware注意到也没有必要将totalsecs
作为属性。
引用他的评论:关于Python属性的好处是你不需要将所有东西变成getter和setter来保持一致的界面,就像你在某些语言中那样。
将totalsecs
设置为属性(只读)可能有一个优势,因为出于某种原因,您希望隐藏MyTime
的内部实现(显然重新整合increment()
法)。
答案 1 :(得分:1)
你可以试试这个;
# calculate total seconds to represent
self.totalsecs = hrs*3600 + mins*60 + secs
self.set_times()
def incerment(self, t):
# increase the time by t amount
self.totalsecs = self.hours * 3600 + self.minutes * 60 + self.seconds + t
self.set_times()
def set_times(self):
self.hours = self.totalsecs // 3600 # split in h, m, s
leftoversecs = self.totalsecs % 3600
self.minutes = leftoversecs // 60
self.seconds = leftoversecs % 60
答案 2 :(得分:0)
主要更改是您应该在incerment
中使用__init__
,因为您的init包含的代码基本相同。
答案 3 :(得分:0)
我可能会将“totalsecs”的访问权限分解为属性,然后使用:
class MyTime:
def __init__(self, hrs=0, mins=0, secs=0,):
""" Create a new MyTime object initialized to hrs, mins, secs.
The values of mins and secs may be outside the range 0-59,
but the resulting MyTime object will be normalized.
"""
self.totalsecs = hrs*3600 + mins*60 + secs
@property
def totalsecs(self):
return self.hours * 3600 + self.minutes * 60 + self.seconds
@totalsecs.setter
def totalsecs(self, totalsecs):
self.hours = totalsecs // 3600 # split in h, m, s
leftoversecs = totalsecs % 3600
self.minutes = leftoversecs // 60
self.seconds = leftoversecs % 60
def increment(self,t):
# increase the time by t amount
self.totalsecs += t
当然,如果你这样做,你就不再需要increment()
方法了。
此外,如果您以后决定切换到Rik Poggi的解决方案并只存储totalsecs值并将小时,分钟,秒数转换为属性,则您只需进行最少的更改。