Python: if w postaci jednej linijki nie działa z pass

9-sie-2019

W Pythonie wyrażenie if można zapisać w postaci jednolinijkowca:

expr1 if cond else expr2

Jednak łatwo wpaść w pułapkę. Takie wyrażenie zadziała:

print(price-bonus) if bonus_granted else print(price)

ale już takie nie:

print(price-bonus) if bonus_granted else price = 200
print(price-bonus) if bonus_granted  else pass

Ale po kolei:

price = 10

bonus = 1

bonus_granted = True

A teraz odpowiadając na pytanie. Przypomnijmy, że Pythonie można mieć statement i expressions:

  • statement – coś robi i niekoniecznie cokolwiek zwraca. Przykładem statement jest pass i przypisanie wartości do zmiennych
  • expression – to jest jedna lub więcej instrukcji, które coś zwracają. Przykładem expression jest np dowolny napis, dowolne obliczenie, ale też np. polecenie print (!!!!!!)

Jak sprawdzić czy coś jest expression? Prosto. Do zmiennej przypisz wynik wykonania polecenia, np.:

x = print('Hello')
print("x = {}".format(x))

zwracany wynik to

Hello
x = None

Widać więc, że print (chociaż głównie kojarzy nam się z robieniem czegoś – wyświetlaniem napisu) jest też expression, bo ma wartość None.

Trochę inaczej jest tu:

x = pass
print("x = {}".format(x))

oto wynik:

  File "C:/temp/tests.py", line 18
    x = pass
           ^
SyntaxError: invalid syntax

Niestety – pass tylko coś robi (dokładniej rzecz biorąc „robi nic”), kompletnie nic nie zwraca, nawet None (!!!!)

Podobnie jest z przypisaniem:

x = (y=6)
print("x = {}".format(x))

też błąd:

  File "C:/temp/tests.py", line 21
    x = (y=6)
          ^
SyntaxError: invalid syntax

Przypisanie się wykonuje, ale podobnie jak poprzednio kompletnie nic nie zwraca.

No i po tym wstępie mogę tłumaczyć dlaczego nie zadziałało if 🙂

Wyrażenie if zapisane w postaci jednolinijkowca musi być wyrażeniem. Pierwsze polecenie:

print(price-bonus) if bonus_granted else price = 200

nie jest wyrażeniem, bo o ile jeszcze print coś zwraca (None), o tyle druga część z przypisaniem nic nie zwraca. Stąd błąd

Podobnie będzie tu:

print(price-bonus) if bonus_granted  else pass

Ale za to tutaj już tego problemu nie ma, bo tu zawsze uzyskasz wyrażenie:

print(price-bonus) if bonus_granted else print(price)

Co ciekawe, jeśli wynik tego wyrażenia chcesz zapisać w zmiennej:

x = print(price-bonus) if bonus_granted else print(price)
print("x = {}".format(x))

to okaże się, że jej wartość to None:

9
x = None

Więcej na ten temat można poczytać też tu (j.ang):

https://stackoverflow.com/questions/16114003/error-when-trying-to-use-pass-keyword-in-one-line-if-statement

Mam nadzieję, że udało mi się rozwiać wątpliwości

Komentarze są wyłączone

Autor: Rafał Kraik