Python3 / Классы / ООП / Как изменить собственные значения объектов с помощью метода? - PullRequest
4 голосов
/ 19 февраля 2012

Я изучаю использование Python Как думать, как ученый: изучите Python 3.

Я изучаю ООП и собрал некоторый код, чтобы ответить на вопрос в книге, но я чувствую, чтоЯ должен был сделать что-то еще.

Код, о котором идет речь, 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 ]

4 голосов
/ 19 февраля 2012

Это чувство как будто вы должны были сделать что-то еще это потому что 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 - вам не нужно превращать все в методы получения и установки, чтобы поддерживать согласованный интерфейс, как в некоторых языках.

Может быть преимуществом установка totalsecs в качестве свойства (только для чтения), только если по какой-то причине вы хотите скрыть внутреннюю реализацию MyTime (очевидно, реинтеграцию метода increment()).

1 голос
/ 19 февраля 2012

Вы можете попробовать это;

   # 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
0 голосов
/ 19 февраля 2012

Я бы, вероятно, выделил бы доступ к 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(). Кроме того, если позже вы решите переключиться на решение Рика Поджи и просто сохранить значение totalsecs и вместо часов внести в свойства часы, минуты и секунды.

0 голосов
/ 19 февраля 2012

Основное изменение заключается в том, что вы должны использовать incerment в __init__, так как ваш init содержит практически тот же код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...