„elif” w warunkach rozumienia listy

129

Czy możemy używać elifw zrozumieniu listy?

Przykład:

l = [1, 2, 3, 4, 5]

for values in l:
    if values==1:
        print 'yes'
    elif values==2:
        print 'no'
    else:
        print 'idle'

Czy możemy włączyć do elifnaszego rozumienia listy, podobnie jak w powyższym kodzie?

Na przykład odpowiedź taka:

['yes', 'no', 'idle', 'idle', 'idle']

Do tej pory używałem tylko ifi ze elsezrozumieniem listy.

samego siebie
źródło

Odpowiedzi:

250

Wyrażenia warunkowe w Pythonie zostały zaprojektowane dokładnie do tego rodzaju przypadków użycia:

>>> l = [1, 2, 3, 4, 5]
>>> ['yes' if v == 1 else 'no' if v == 2 else 'idle' for v in l]
['yes', 'no', 'idle', 'idle', 'idle']

Mam nadzieję że to pomoże :-)

Raymond Hettinger
źródło
5
W składni jest trochę interesującej historii. Przez wiele lat przed ich wprowadzeniem „trzeciorzędne wyrażenia” były jedną z pięciu najbardziej pożądanych zmian w języku. Ponieważ Guido van Rossum wyraźnie zaprojektował go jako język oparty na wypowiedziach, przez długi czas stanowczo stawiał opór (wyrażenia trzeciorzędne, a zwłaszcza ich nadużywanie, są źródłem wielu niejasności w kodzie). Kiedy w końcu uległ, oznajmił, że celowo wybrał składnię, która zniechęca do nadużywania. Mimo to, jak zwykle, wykonał elegancką pracę projektową.
holdenweb
1
Ternary, cholera (pisał, dostrzegając swój dyslektyczny błąd zbyt późno, by go edytować).
holdenweb
2
Kiedy głosuję za tą odpowiedzią, chcę wspomnieć o tym: dla 1 pary if / else jest łatwe do odczytania, 2 pary: coraz trudniej jest to zrozumieć. Nie wspominaj nawet o 3 parach. Jeśli wyrażenie wymaga 3 lub więcej par, słownik lub oddzielna funkcja ułatwi czytanie i zrozumienie.
Hai Vu
1
Chciałbym dodać nie rozwiązanie tego problemu, ale przypomnienie o czystym kodzie: ponieważ to rozumienie listy ma trzy warunki warunkowe, prawdopodobnie można by było przekształcić je w metodę bardziej opisową. Chodzi mi o to: martinfowler.com/bliki/FunctionLength.html :)
Alvaro Cavalcanti
Natknąłem się na przypadek, w którym potrzebowałem elif, ale tylko dwie wartości. Korzystając z tego przykładu, musiałbym po prostu ['yes', 'no']zostać stworzony. Aby to zrobić, można zrobić: ['yes' if v == 1 else 'no' for v in l if values in [1,2]]. Obecnie nie mogę wymyślić prostszego sposobu, aby to zrobić.
dTanMan
48
>>> d = {1: 'yes', 2: 'no'}
>>> [d.get(x, 'idle') for x in l]
['yes', 'no', 'idle', 'idle', 'idle']
Ignacio Vazquez-Abrams
źródło
4
Myślę, że ten formularz jest o wiele łatwiejszy do strawienia niż próba wykonania naprawdę długiej i skomplikowanej logiki if / else w ramach listy comp
jdi
5
@jdi Chociaż wyrażenia warunkowe mogą nie odpowiadać Twojemu gustowi, zostały specjalnie zaprojektowane do obsługi łańcuchów if-elif-elif-else, tak jak żądał OP. Nie są one trudne do opanowania i może bezpiecznie obsłużyć sytuacje, które nie są tak podatne na słowniku logiki odnośników: 'A' if grade>=90 else 'B' if grade>=80 else 'C' if grade>=70 else 'F'.
Raymond Hettinger
1
Czy jest korzyść z definiowania dpoza zrozumieniem?
Chris_Rands
Powodem, dla którego bardziej podoba mi się rozumienie listy, jest to, że czyta się ją tak, jak angielski. Nawet nie-programista byłby w stanie zrozumieć, co robi. W przypadku tego rozwiązania musisz zrozumieć metodę dict.get ().
Tim Skov Jacobsen
26

W pewnym sensie możesz.

Zauważ, że kiedy używasz sytax, takich jak:

['yes' if v == 1 else 'no' for v in l]

Używasz trójskładnikowej formy operatora if / else (jeśli znasz języki takie jak C, wygląda to jak ?:konstrukcja (v == 1 ? 'yes' : 'no'):).

Postać trójskładnikowa operatora if / else nie ma wbudowanego elementu „elif”, ale można go zasymulować w warunku „else”:

['yes' if v == 1 else 'no' if v == 2 else 'idle' for v in l]

To tak, jakby powiedzieć:

for v in l:
    if v == 1 :
        print 'yes'
    else:
        if v == 2:
            print 'no'
        else:
            print 'idle'

Nie ma więc bezpośredniej konstrukcji „elif”, o którą pytałeś, ale można ją zasymulować za pomocą zagnieżdżonych instrukcji if / else.

kawa matematyczna
źródło
1
Ostatni kod akapitu jest bardzo wnikliwy dzięki!
devianceee
3

Może chcesz tego:

l = [1, 2, 3, 4, 5] 

print ([['idle','no','yes'][2*(n==1)+(n==2)] for n in l])
Ratnesh Kushwaha
źródło
2

Możesz użyć rozumienia list, jeśli zamierzasz utworzyć inną listę na podstawie oryginału.

>>> l = [1, 2, 3, 4, 5]
>>> result_map = {1: 'yes', 2: 'no'}
>>> [result_map[x] if x in result_map else 'idle' for x in l]
['yes', 'no', 'idle', 'idle', 'idle']
San4ez
źródło
2

Innym prostym sposobem jest użycie list warunkowych w następujący sposób:

l=[1,2,3,4,5]
print [[["no","yes"][v==1],"idle"][v!=1 and v!=2] for v in l]

daje prawidłową odpowiedź:

[„tak”, „nie”, „bezczynny”, „bezczynny”, „bezczynny”]

Stefana Gruenwalda
źródło