2017-02-13 19 views
5

Próbuję zaimplementować leniwą właściwość. Powiedzmy, obiekt jest zainicjowana przez object._x = None, a następnie chcę napisać cośpython: wyrażenie może być wyrażeniem wewnętrznym?

@property 
def x(self): 
    return self._x or (init_x_value(); x) 

tak, że inicjator nazywa się tylko za pierwszym razem atrybut jest wzrok.

W scala wyrażenie może zawierać instrukcje. Czy coś podobnego jest możliwe w python. Jeśli nie, czy jest jakiś inny sposób na jego wdrożenie, czy powinienem pozostawać z if-else?

+0

'init_x_value' zwraca' None' prawo? –

+1

O ile mi wiadomo, nie można tego zrobić, co jest jednym z powodów, dla których "lambda" jest tak ograniczona w Pythonie. – melpomene

+0

@WillemVanOnsem: może, po prostu obliczyć wartość '_x' i zapisać ją w obiekcie –

Odpowiedz

6

Jeśli init_x_valuepowraca None, można po prostu użyć:

return self._x or init_x_value() or self._x 

Uwaga jednak, jak @3Doubloons mówi w swoim komentarzu, że jeśli self._x jest coś false-owski jak None, [] (pusty list), () pusta krotka lub klasa, która zastąpiła metodę __bool__, przejdzie do metody init, która może być kosztowna pod względem obliczeniowym.

W przypadku init_x_valuepowraca obliczona x wartość sama w sobie, można nawet napisać, że lubię:

return self._x or init_x_value() 

To dlatego, że or w Pythonie jest dość szczególny: z x or y działa jak:

if bool(x): 
    return x 
else: 
    return y 

i x i y są generowane leniwie. Od bool(None) jest False w pierwszym przypadku, więc sprawdzi to self._x. Jeśli self._x jest None, będzie kontynuował, wywołując init_x_value(), ponieważ ta metoda nie zwraca niczego, co niejawnie zwraca None, która nie jest akceptowana przez partycję or, więc w końcu ustala ostatnią self._x, która jest teraz ustawiona.

+0

Miło, nie przyszło mi użyć podwójnego 'lub'. Jednakże, jeśli chcesz, aby oświadczenie, a nie wywołanie funkcji, nie sposób to zrobić, prawda? –

+0

@blue_note: nie tak daleko, jak wiem, ponieważ zadanie nie ma wyniku (nic nie zwraca). –

+0

Musisz zachować ostrożność przy takim podejściu. Jeśli 'self._x' jest falsey,' init_x_values' będzie wywoływane za każdym razem. – 3Doubloons

5

Aby odpowiedzieć na pytanie tytułowe: nie, w języku Python wyrażenie nie może zawierać instrukcji. Kropka.

Prawidłowe pythonic sposób napisać getter jest:

@property 
def x(self): 
    # assume _x defaults to None 
    if self._x is None: 
     # here you can have has many statements as 
     # you like ;) 
     self._x = init_x_value() 
    return self._x 

może nie wyglądać tak mądry jak potrójny „lub” lub sprawozdania inline lub cokolwiek, ale jest to tak proste, proste, jasne i czytelny jak to może być.

1

można ukryć oświadczenia w funkcji:

@property 
def x(self): 
    def initialize_and_return_x(): 
     init_x_value() 
     return self._x 
    return self._x or initialize_and_return_x() 
Powiązane problemy