Назначение Python и проверка функции с использованием elif

Я видел подобные вопросы, но не совсем то же самое. У меня есть выражение

if foo == ....
  return -1
elif myFunction(bar) != -1:
  return myFunction(bar)
elif ...

Я не хочу дважды вычислять myFunction(bar). Если бы это был просто if, я мог бы сделать

temp = myFunction(bar)
if temp != -1
  return temp

Однако выполнение этого с помощью elif приведет к ненужным вычислениям temp, если мы будем следовать intitial if.

Я вижу решение с помощью

if ...
else
  temp = myFunction(bar)
  if temp != -1:
    return temp
  elif ...

Но теперь это становится более уродливым. Есть ли лучший способ сделать это?

Ответ 1

Если вы сделаете это много, он может заплатить за memoizing decorator. Единственный memoizer, который в настоящее время находится в стандартной библиотеке (для более нового Python 3.x), является lru_cache, что является излишним, но показывает общую идею:

>>> def func():
...     print("foo")
...     return 1
... 
>>> if func():
...     print(func())
...     
foo
foo
1

Теперь memoize func:

>>> from functools import lru_cache
>>> func = lru_cache(1)(func)
>>> if func():
...    print(func())
...     
foo
1

Ответ 2

Если вы не хотите дважды вызывать myFunction (bar), тогда нет другого способа, кроме использования промежуточной переменной для хранения результата. Люди здесь начинают предлагать для этого сложные решения для кеширования. Это может быть довольно удобно в крайних случаях, но прежде чем это сделать, немного вернемся к основам. Вы должны правильно использовать тот факт, что хотите вернуться из своих условных блоков. В этих ситуациях вы можете сохранить много else s. Ниже следует, что в основном это блок кода из вашего вопроса, но без точек, с правильным отступом и с именами в соответствии с PEP8:

if foo == "bar"
    return -1
elif myfunction(bar) != -1:
    return myfunction(bar)
else
    return None

Его легко заменить на:

if foo == "bar"
    return -1
t = myfunction(bar)
if t != -1:
    return t
return None

Как уже было сказано в другом ответе, вы можете дважды вызвать свою функцию, если это не влияет на производительность вашего кода. Результат будет выглядеть так же просто, как

if foo == "bar"
    return -1
if myfunction(bar) != -1:
    return myfunction(bar)
return None

Ответ 3

Если ваш вызов функции достаточно прост, вы можете пойти с вызовом дважды. Python не поддерживает функцию назначения и сравнения. Таким образом, вы должны обмениваться читабельностью/элегантностью с производительностью.

Ответ 4

вы также можете сделать функцию promise следующим образом:

class Promise():
    def __init__(self, func):
        self.__func = func;
        self.__computed = False;

    def Get(self):
        if not self.__computed:
            self.__result = self.__func()
            self.__computed = True
        return self.__result

def func(text):
    print text
    return 1

    f = Promise(lambda: func("compute"))
    >>> f.Get()     # first call, compute
    compute
    1
    >>> f.Get()     # second call, return result
    1