2013-07-22 15 views
12

Widziałem pytania podobne do tego, ale nie do końca takie same. Mam wyrażenie:Przypisanie Pythona i test funkcji przy użyciu elif

Nie chcę dwukrotnie obliczać myFunction(bar). Gdyby to było po prostu if mogłem zrobić

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

Jednak robi to z elif spowoduje niepotrzebnych obliczeń temp gdybyśmy śledzić intitial if.

widzę rozwiązanie używając

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

Ale teraz zaczyna być bardziej brzydkie. Czy istnieje lepszy sposób na osiągnięcie tego?

+0

Jeśli nie chcesz, aby zadzwonić 'myFunction (bar)' dwa razy i jeśli tylko może/chcesz wywołać to po sprawdzeniu 'foo', to nie ma innego sposobu niż użycie pośredniej zmiennej do przechowywania wyniku. Nie ma magii, aby ominąć ten podstawowy problem logiczny :-). Myślę, że rozwiązanie nie jest brzydkie, gdy odzwierciedla właściwą logikę. Musisz tylko uważać, gdzie umieścić ostatni "elif". –

+2

Ale 'if' (przynajmniej w przykładzie) i tak zawiera' return', więc możesz * po prostu użyć tymczasowej wartości i rozpocząć nowy blok 'if'. – Volatility

Odpowiedz

6

Jeśli zrobisz to bardzo często, być może zapłacisz, aby mieć około memoizing decorator. Jedynym memoizer który znajduje się obecnie w bibliotece standardowej (dla nowszych Python 3.x) jest lru_cache, co jest przesadą, ale pokazuje ogólny pomysł:

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

Teraz memoize func:

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

+1, pokonaj mnie i nie wymyślaj ponownie koła. –

+0

"Jeśli robisz to dużo", kluczową kwestią jest tutaj.W przeciwnym razie całe podejście jest po prostu OTT. –

1

If twoja funkcja jest wystarczająco prosta, możesz zadzwonić dwa razy. Python nie obsługuje funkcji przypisywania i porównywania. Tak więc, musisz odrzucić wydajność/elegancję.

5

Jeśli nie chcesz dwukrotnie wywoływać funkcji myFunction (bar), nie ma innego sposobu niż użycie zmiennej pośredniej do zapisania wyniku. Tutaj ludzie zaczynają proponować kompleksowe rozwiązania buforowania. W skrajnych przypadkach może to być wygodne, ale zanim to zrobimy, powróćmy do podstaw. Powinieneś właściwie wykorzystać fakt, że chcesz powrócić z bloków warunkowych. W takich sytuacjach można zaoszczędzić wiele plików else. Co za tym idzie teraz w zasadzie jest blok kodu z Twojego pytania, ale bez kropek, z odpowiednim wcięciem, a wraz z nazwami według PEP8:

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

To może być łatwo zastąpiony:

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

jak już w innej odpowiedzi można wywołać funkcję dwa razy, jeśli nie ma to wpływu na działanie twojego kodu. Rezultatem będzie wyglądać tak proste, jak

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

można również funkcją promise tak:

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 
Powiązane problemy