2012-12-31 13 views
20

jestem dość obeznany z potrójnym podejściu operatora Pythona:Kompresja `x jeśli x indziej y` oświadczenie w Pythonie

value = foo if something else bar 

moje pytanie jest bardzo prosta: bez wcześniejszych zadań, czy jest tak, aby odwoływać się do pojęcia bytu ocenione w (if ...) z jednego z argumentów operacji powrotu (... if lub else ...)?

Motywacją jest to, że czasami używam wyrażeń w if ..., które są dokładnie tym, co chciałbym mieć w wyniku operacji trójskładnikowej; zdarza się jednak, że dla małych wyrażeń nie ma problemu z powtórzeniem go, ale dla nieco dłuższych wyrażeń, robi się trochę paskudnie. Weź to jako przykład:

value = info.findNext("b") if info.findNext("b") else "Oompa Loompa" 
+0

Cóż, Oompa Loompa jest zabawna! –

+0

@AspiringAqib nie mamy zadania, ale nadal możemy cieszyć się loompami oompa (: – Rubens

+0

cóż, masz rozwiązanie na dole huh? –

Odpowiedz

23

Nie ma sposobu, aby to zrobić, i to jest celowe. Trójskładnik, jeśli ma być użyty tylko do trywialnych przypadków.

Jeśli chcesz korzystać z jego wynik obliczeń dwukrotnie, umieścić go w zmiennej tymczasowej:

value = info.findNext("b") 
value = value if value else "Oompa Loompa" 

Gdy to zrobisz, to staje się jasne, że robisz coś głupiego, a w rzeczywistości pythonic sposób napisać to:

value = info.findNext("b") 
if not value: 
    value = "Oompa Loompa" 

I to rzeczywiście 5 mniej klawiszy niż w pierwotnej próbie.

Jeśli naprawdę chcesz zapisać naciśnięcia klawiszy, można zamiast tego zrobić:

value = info.findNext("b") or "Oompa Loompa" 

Ale to zniechęca wielu przewodnikach stylu, a przez BDFL.

Jeśli robisz to tylko raz, lepiej być bardziej konkretnym. Jeśli robisz to pół tuzina razy, to jest trywialne, i znacznie lepiej, aby findNext wziąć opcjonalną domyślne, aby powrócić zamiast None, podobnie jak wszystkie te wbudowane i stdlib funkcje:

def findNext(self, needle, defvalue=None): 
    # same code as before, but instead of return None or falling off the end, 
    # just return defvalue. 

Następnie możesz to zrobić:

value = info.findNext("b", "Oompa Loompa") 
+0

Naprawdę mam pewne dziwne tiki z programowaniem: nie lubię pisać więcej niż 70 kolumn, i naprawdę doceniam rozwiązania jednoliniowe; problemem jest raczej zwartość niż wyraźna liczba słów. Przyjmuję jednak twoją odpowiedź, gdy odpowiadasz "tak/nie" na moje pytanie binarne. Zgadzając się jednak, że używanie lub, jak wskazano przez @Ignacio, jest w końcu najlepszym rozwiązaniem. – Rubens

+0

Zwracanie "Brak" jest tym samym, co zwracanie 'null', a zatem [tak samo złe] (http://en.wikipedia.org/wiki/Void_safety). –

+1

@Rubens: Pythonowy sposób pisania rozwiązań 1-liniowych polega na zawijaniu wszystkiego, co skomplikowane w jawnej funkcji. Jeśli możesz dodać 'defval' do' findNext', zrób to; jeśli nie możesz, napisz opakowanie. Różne języki mają różne style idiomatyczne (np. W Haskell, nazywając funkcję, którą będziesz tylko wywoływać, gdy jest to zapach kodu), a różne języki bardziej przylegają do swoich idiomów (np. W perlu, "Jest tylko jeden sposób, aby zrobić "będzie uważany za błąd, a nie funkcję). Ale jeśli wybrałeś Python, powinieneś nauczyć się idiomatycznego Pythona. – abarnert

20

Nie używaj w ogóle if ... else. Zamiast tego skorzystaj z koalescencyjnych operatorów Pythona.

value = info.findNext("b") or "Oompa Loompa" 
+1

To jest [z pewnością skrót] (http: // docs.python.org/2/library/stdtypes.html#boolean- operations-and-or-not), @Rubens. 'x lub y' powinno kompilować się do tego samego kodu co' if bool (x), a następnie x else y'. 'bool' nazywa' .__ nonzero __() '. –

+1

Możesz to zrobić, ale to nie znaczy, że powinieneś. Jeśli robisz to wystarczająco długo, aby zapisać 5 naciśnięć klawiszy, zmodyfikuj metodę 'findNext', aby uzyskać wartość domyślną. W przeciwnym razie zapisz go jawnie. – abarnert

Powiązane problemy