Как и где вычислять производные переменные экземпляра в python

У меня есть класс с переменной экземпляра str. Из этой переменной экземпляра я вычисляю вторую переменную экземпляра, которая представляет собой просто строку, разбитую на определенные «атомы». Вторая переменная экземпляра полностью определяется первой. Я сделал ее переменной экземпляра, потому что считаю, что ее лучше всего рассматривать как «свойство» класса. Я немного не уверен, как обращаться с производными переменными экземпляра. Особенно:

1) Я думаю, что они должны быть доступны только для получения. Однако, поскольку вычисление производной переменной экземпляра довольно интенсивное, я хочу, чтобы оно выполнялось при инициации класса, а не при вызове переменной. 2) Если я делаю функцию исключительно для вычисления переменной экземпляра, есть ли способ пометить это? 3) Кроме того, я должен передать первую переменную экземпляра в качестве параметра или просто прочитать ее в методе от себя? (в общем, я все еще немного не уверен, когда передавать переменные экземпляра в качестве параметров методам.) 4) Есть ли лучший способ сделать это, о котором я не упомянул? Спасибо

РЕДАКТИРОВАТЬ: Вот упрощенный пример того, что я имею в виду:

class Amendment:

    def __init__(self, string):
        self.string = string
        self.atoms = generate_atoms()


    def generate_atoms():
        return do_something_that_takes_long(self.string)

person Neil    schedule 20.05.2018    source источник
comment
У вас больше шансов получить помощь в этом, если вы опубликуете небольшой пример, чтобы мы точно знали, как вы строите этот класс (нам не нужно видеть детали вашего фактического алгоритма построения атома, достаточно упрощенной версии) . И таким образом мы можем использовать имена атрибутов из вашего кода, вместо того, чтобы говорить о первой переменной экземпляра и т.д.   -  person PM 2Ring    schedule 20.05.2018
comment
Между тем, изменяется ли первая переменная экземпляра в течение жизни экземпляра?   -  person PM 2Ring    schedule 20.05.2018
comment
Отредактировано. И нет, переменная первого экземпляра не будет изменена. Следовательно, вычисление атомов может произойти один раз, а затем сохраниться в этом объекте навсегда.   -  person Neil    schedule 20.05.2018
comment
Спасибо. Итак, вы хотите, чтобы свойства .string и .atoms были доступны только для чтения?   -  person PM 2Ring    schedule 20.05.2018
comment
Да, .string также будет доступен только для получения   -  person Neil    schedule 20.05.2018


Ответы (1)


Вы забыли self в нескольких местах. Но вот как сделать свойства .string и .atoms доступными только для чтения. Мы используем пару атрибутов "private", которые создаются во время __init__ и используйте @property для создания реальных геттеров.

class Amendment:
    def __init__(self, string):
        self._string = string
        self._atoms = self.generate_atoms()

    def generate_atoms(self):
        #return do_something_that_takes_long(self.string)
        return list(self.string)

    @property
    def string(self):
        return self._string

    @property
    def atoms(self):
        return self._atoms

# Test

a = Amendment('abc')
print(a.string, a.atoms)
# This will raise an error because `.string` is a get-only property.
a.string = 'xyz'

вывод

abc ['a', 'b', 'c']
Traceback (most recent call last):
  File "./qtest.py", line 53, in <module>
    a.string = 'xyz'
AttributeError: can't set attribute

Если хотите, вы также можете пометить generate_atoms как личное, но, вероятно, в этом нет необходимости. И в любом случае ничто не мешает настойчивому пользователю получить доступ к таким вещам, как объясняют связанные документы.

Что касается вашего третьего вопроса, методы обычно должны получать доступ к нужным им атрибутам через self. В некоторых случаях вы можете использовать один и тот же метод для разных атрибутов, и тогда имеет смысл передать атрибут в качестве параметра, но если это не так, это просто выглядит странно. ;)

person PM 2Ring    schedule 20.05.2018
comment
Круто, выглядит аккуратно. Спасибо! - person Neil; 20.05.2018
comment
@Нил Не беспокойся. Я добавил еще несколько замечаний к своему ответу. - person PM 2Ring; 20.05.2018