Python3 / Classes / OOP /如何使用方法更改对象自身值?

时间:2012-02-19 09:16:04

标签: python oop class python-3.x

我正在学习使用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)

那怎么样? 有没有办法清理它?

4 个答案:

答案 0 :(得分:4)

感觉就像你应该做的其他事情因为hoursminutesseconds属性

您不需要将这些值存储为对象的属性,只是希望能够在需要时访问这些值。

调用类似的内容:

>>> 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值并将小时,分钟,秒数转换为属性,则您只需进行最少的更改。