Проверьте, была ли определена переменная класса
Я имею дело со сценарием, где у меня есть класс Python Foo. Фу, между прочим, делает много больших вычислений, которые я бы не делал, если бы не требовал. Итак, когда я определяю метод получения для одного из этих больших вычислений, как мне убедиться, что метод, соответствующий вычислению (здесь bigcalculation()), уже запущен?
class Foo:
def __init__(self):
#initialize some stuff
def bigcalculation(self):
#perform calculation
self.big_calc_result=[big list of numbers];
def get_big_calc_result(self):
if hasattr(self,'big_calc_result')==False:
self.bigcalculations();
return sef.big_calc_result;
Если его запустить один раз, я не хочу, чтобы он снова запускался. и я не хочу, чтобы вызывающий абонент отслеживал, запустился ли он один раз или нет.
Теперь я делаю это с помощью функции hasattr(), как описано выше, но я думаю, что это действительно ужасный способ сделать это. Есть ли более элегантный способ сделать это?
Альтернативой, которую я могу придумать, является определение в моей функции init() всех переменных, которые я бы когда-либо использовал в классе, как пустой список. Затем проверьте, является ли big_calc_result пустым списком или нет, чтобы определить, выполнялся ли self.bigcalculation(). Это лучший подход?
связанный вопрос:Python позволяет мне определять переменные на лету в классе. Но разве это плохая практика программирования?
Изменить: Оглядываясь назад, я также обнаружил, что использование исключений также может быть еще одним способом решения этой ситуации. Это может быть более питонический способ делать вещи.
def get_big_calc_result(self):
try:
return self.big_calc_result;
except AttributeError:
self.bigcalculations();
return self.big_calc_result;
Ответы на этот вопрос полезны: проверка существования члена в Python
1 ответ
Вы можете запомнить результат и сохранить его как свойство:
class Foo(object):
def __init__(self):
self._big_calc_result = None
@property
def big_calc_result(self):
if self._big_calc_result is not None:
return self._big_calc_result
else:
self._big_calc_result = self.big_calc_run()
return self._big_calc_result
def big_calc_run(self):
time.sleep(10) # Takes a long time ...
Теперь вы просто инициализируете класс и получаете результат:
f = Foo()
x = f.big_calc_result
y = f.bic_calc_result # Look mom, this happened really quick
Конечно, вам не нужно использовать свойство, если оно менее интуитивно понятно, и вы можете изменить здесь все в соответствии с API, который вы пытаетесь предоставить. Настоящий смысл заключается в кешировании результата в переменную с префиксом подчеркивания, которая гласит: "Это деталь реализации - если вы возитесь с ней, вы заслуживаете того, чтобы ваш код сломался в какой-то момент в будущем".