Геттер с побочным эффектом - PullRequest
13 голосов
/ 19 января 2011

Я создаю класс, чьи объекты инициализируются с помощью набора XML-кода.Класс имеет возможность извлекать различные параметры из этого XML и кэшировать их внутри переменных состояния объекта.Потенциальное количество этих параметров велико, и, скорее всего, пользователю не понадобится большинство из них.Вот почему я решил выполнить «ленивую» инициализацию.

В следующем тестовом примере такой параметр равен title.Когда пользователь пытается получить к нему доступ в первый раз, функция получения анализирует XML, правильно инициализирует переменную состояния и возвращает ее значение:

class MyClass(object):     
    def __init__(self, xml=None):
        self.xml  = xml
        self.title = None

    def get_title(self):
        if self.__title is None:
            self.__title = self.__title_from_xml()
        return self.__title

    def set_title(self, value):
        self.__title = value

    title = property(get_title, set_title, None, "Citation title")

    def __title_from_xml(self):
        #parse the XML and return the title
        return title         

Это выглядит хорошо и прекрасно работает для меня.Тем не менее, меня немного беспокоит тот факт, что функция getter на самом деле является «установочной» в том смысле, что она имеет очень существенный побочный эффект на объект.Это законное беспокойство?Если да, то как мне это решить?

Ответы [ 3 ]

14 голосов
/ 19 января 2011

Этот шаблон проектирования называется Ленивая инициализация , и он имеет законное использование.

4 голосов
/ 19 января 2011

Хотя геттер, безусловно, выполняет побочный эффект, традиционно это не то, что можно считать плохим побочным эффектом. Поскольку метод получения всегда возвращает одно и то же (исключая любые промежуточные изменения в состоянии), он не имеет видимых для пользователя побочных эффектов. Это типичное использование для свойств, поэтому не о чем беспокоиться.

0 голосов
/ 24 ноября 2017

Спустя несколько лет, но хорошо: хотя ленивая инициализация хороша сама по себе, я бы определенно не откладывал парсинг xml и т. Д., Пока кто-то не получит доступ к title объекта.Предполагается, что вычисляемые атрибуты ведут себя как простые атрибуты, а доступ к простым атрибутам никогда не повысится (при условии, что атрибут, конечно, существует).

FWIW У меня был очень похожий случай в каком-то проекте, который я взял на себя, с ошибками синтаксического анализа xml, возникающими в самых неожиданных местах, из-за того, что предыдущий разработчик использовал свойства точно так же, как в примере OP,чтобы исправить это, поместив часть анализа и проверки во время создания экземпляра.

Итак, используйте свойства для отложенной инициализации, только если и когда вы знаете, , первый доступ никогда не будет повышаться.На самом деле, никогда не используйте свойство для чего-либо, что может поднять (по крайней мере, при получении - установка в другой ситуации).Иначе, не используйте свойство, сделайте метод получения явным методом и четко документируйте, что оно может вызвать то или иное.

Примечание: использование свойства для кэширования чего-либо здесь не является проблемой, само по себе это нормально.

...