Zrozumienie listy jednowierszowej: warianty if-else

178

Chodzi bardziej o składnię rozumienia list w Pythonie. Mam listę, która tworzy listę liczb nieparzystych z danego zakresu:

[x for x in range(1, 10) if x % 2]

To tworzy filtr - mam listę źródeł, z której usuwam liczby parzyste ( if x % 2). Chciałbym użyć tutaj czegoś takiego jak if-then-else. Poniższy kod nie działa:

>>> [x for x in range(1, 10) if x % 2 else x * 100]
  File "<stdin>", line 1
    [x for x in range(1, 10) if x % 2 else x * 100]
                                         ^
SyntaxError: invalid syntax

Istnieje wyrażenie Pythona, takie jak if-else:

1 if 0 is 0 else 3

Jak go używać w ramach rozumienia listy?

ducin
źródło
1
Co to jest warte, masz „rozumienie listy”, a nie generator. Ostateczna składnia jest taka sama, z wyjątkiem tego, że generatory używają ()zamiast [].
mgilson
2
Zajęło mi trochę czasu, aby dowiedzieć się, dlaczego if x % 2 eliminuje liczby parzyste (zamiast je zachować) - dzieje się tak dlatego, że kiedy xjest nawet x % 2wynikiem wyrażenia 0, które z kolei jest wartościowane do False, podczas gdy każdy intz wyjątkiem 0oblicza do True.

Odpowiedzi:

328

x if y else zto składnia wyrażenia, które zwracasz dla każdego elementu. Potrzebujesz więc:

[ x if x%2 else x*100 for x in range(1, 10) ]

Nieporozumienie wynika z faktu, że w pierwszym przykładzie używasz filtra , ale nie w drugim. W drugim przykładzie jesteś tylko mapowanie każdej wartości do drugiego, używając wyrażenia trójargumentowy-operatora.

Z filtrem potrzebujesz:

[ EXP for x in seq if COND ]

Bez filtra potrzebujesz:

[ EXP for x in seq ]

aw twoim drugim przykładzie wyrażenie jest „złożone”, które obejmuje rozszerzenie if-else.

shx2
źródło
2
Mam jedno pytanie ... [x for x in range(1, 10) if x % 2]jest poprawna składnia. [x if x % 2 for x in range(1, 10)]- to nie jest, ale [x if x%2 else x*100 for x in range(1, 10)]znowu jest, poprawna składnia. Dlaczego?
ducin
@tkoomzaaskz w twoim drugim przykładzie, nie jest to ani operator trójskładnikowy (brak else), ani filtr (ponieważ znajduje się na EXPczęści listy)
shx2
3
@tkoomzaaskz Aby jeszcze bardziej wyjaśnić, zwróć uwagę, że ifna końcu możesz dodać drugi : [x if x%2 else x*100 for x in range(1, 10) if not x%3]pierwszy ifjest częścią operatora trójskładnikowego, a drugi ifjest częścią składni list złożonych. Całość x if x%2 else x*100jest „na tym samym poziomie” co proste 2*x, jest to wyrażenie do oceny po lewej stronie for, gdy filtrowanie if not x%3już miało miejsce.
zx81
Witam, czy jednowierszowa instrukcja byłaby bardziej wydajna niż umieszczenie jej w dwóch wierszach, takich jak, for i in x:a następnie w pętli for if i == y:?
Alexis.Rolland
23
[x if x % 2 else x * 100 for x in range(1, 10) ]
lucasg
źródło
12

Możesz to zrobić również ze zrozumieniem listy:

A=[[x*100, x][x % 2 != 0] for x in range(1,11)]
print A
Stefana Gruenwalda
źródło
1
Bardzo dobrze. Kawałek logiczny. Dzięki, właśnie dałeś mi łatwiejsze do odczytania rozwiązanie.
Możesz również przypisać podwójnie w ten sposób: A, B = [10,11] [a == 19], [1,14] [a == 20]
Stefan Gruenwald
10

Jeszcze jedno rozwiązanie, mam nadzieję, że komuś się spodoba:

Używanie: [False, True] [Expression]

>>> map(lambda x: [x*100, x][x % 2 != 0], range(1,10))
[1, 200, 3, 400, 5, 600, 7, 800, 9]
>>>
James Sapam
źródło
3

Udało mi się to zrobić

>>> [x if x % 2 != 0 else x * 100 for x in range(1,10)]
    [1, 200, 3, 400, 5, 600, 7, 800, 9]
>>>
anudeep
źródło