Przypisanie warunku-warunku w jednym wierszu


140

Mam następujący kod

num1 = 10
someBoolValue = True

Muszę ustawić wartość num1na, 20jeśli someBoolValuejest True; i nie rób nic innego. Oto mój kod

num1 = 20 if someBoolValue else num1

Czy można w jakiś sposób uniknąć tej ...else num1części, aby wyglądała czysto? Odpowiednik

if someBoolValue:
    num1 = 20

Próbowałem zastępując ją ...else passtak: num1=20 if someBoolValue else pass. Otrzymałem tylko błąd składni. Nie mogłem też po prostu pominąć tej ...else num1części.


2
Po prostu zmień to wszystko na num1 = 20 if someBoolValue else 10. Wtedy też oszczędzasz num1=10linię?
Thomas Ahle

Dzięki. Ale to nie jest dokładnie mój kod. Miałem na myśli, że num1już istnieje ...
bdhar,

Odpowiedzi:


195

Myślę, że nie jest to możliwe w Pythonie, ponieważ to, co faktycznie próbujesz zrobić, prawdopodobnie zostanie rozszerzone do czegoś takiego:

num1 = 20 if someBoolValue else num1

Jeśli wykluczysz else num1, otrzymasz błąd składni, ponieważ jestem pewien, że przypisanie musi faktycznie coś zwrócić.

Jak już wspominali inni, możesz to zrobić, ale jest to złe, ponieważ prawdopodobnie następnym razem będziesz się mylić, czytając ten fragment kodu:

if someBoolValue: num1=20

Nie jestem wielkim fanem z tego num1 = someBoolValue and 20 or num1samego powodu. Muszę pomyśleć dwa razy, co robi ta linia.

Najlepszym sposobem na osiągnięcie tego, co chcesz, jest oryginalna wersja:

if someBoolValue:
    num1 = 20

Powodem, dla którego jest to najlepsza wersja, jest to, że jest bardzo oczywiste, co chcesz zrobić, i nie zmylisz siebie ani kogokolwiek innego, kto będzie miał później kontakt z tym kodem.

Poza tym, na marginesie, num1 = 20 if someBoolValuejest to poprawny kod Ruby, ponieważ Ruby działa nieco inaczej.


8
Zgodnie z PEP-308 ( docs.python.org/2.5/whatsnew/pep-308.html ) wyrażenie warunkowe może być jaśniejsze, jeśli zostanie umieszczone w paren, jak w num1 = (20 if someBoolValue else num1).
haridsv

46

Użyj tego:

num1 = 20 if someBoolValue else num1

3
to jest to, czego używałem .. i szukam alternatywy .. mimo wszystko dzięki!
bdhar

Jak nazwać ten blok? Mam na myśli jak to się nazywa?
fuat

1
jest to operator trójskładnikowy
Chris Maes

Nie należy stosować tego podejścia, jeśli przeglądamy duże zbiory danych, ponieważ wprowadza to niepotrzebne przypisanie na wypadek, gdybyśmy znaleźli się w instrukcji else.
dapc

21

W jednej linii:

if someBoolValue: num1 = 20

Ale nie rób tego. Ten styl nie jest zwykle oczekiwany. Ludzie wolą dłuższą formę dla przejrzystości i spójności.

if someBoolValue:
    num1 = 20

(Należy również unikać czapek wielbłąda. Dlatego raczej używaj some_bool_value.)

Zwróć uwagę, że wyrażenie w wierszu some_value if predicatebez elseczęści nie istnieje, ponieważ nie byłoby wartości zwracanej, gdyby predykat był fałszywy. Jednak we wszystkich przypadkach wyrażenia muszą mieć jasno określoną wartość zwracaną. Różni się to od użycia, na przykład w Rubim lub Perlu.


2
Ponieważ staje się trudny do odczytania i prawdopodobnie zostaniesz zdezorientowany przez własny kod, a to nigdy nie jest dobry pomysł.
Frost

@bdhar, dlaczego chcesz umieścić to w jednej linii? Nie będzie działać szybciej, po prostu innym ludziom będzie trudniej czytać
John La Rooy,

1
@gnibbler, właściwie bez powodu. Szukałem krótszej formy z lepszą czytelnością ..
bdhar

17

możesz użyć jednego z następujących:

(falseVal, trueVal)[TEST]

TEST and trueVal or falseVal

1
Ładne jedno liniowe zadanie warunkowe
minhas23

Jak nazywa się ta „struktura”? Nigdy nie widziałem tego w ciągu ~ 6 miesięcy nauki Pythona.
Guimoute

1
Przynajmniej nie są to zadania, chyba że umieścisz jedno przed nimi, a po drugie, nie będą działać w opisany tutaj sposób. Pierwsza tworzy krotkę, a następnie wybiera jeden z jej elementów według indeksu. Będzie działać tylko w przypadku testów, które zwracają liczbę całkowitą od -1 do 1 lub True/ False, ponieważ booljest to podklasa int. We wszystkich przypadkach, w których test zwraca coś, co po prostu dałoby wynik jako prawda, kończy się niepowodzeniem z wyjątkiem. Drugi działa tylko wtedy, gdy trueValsam nie ocenia fałszu, co skutkowałoby falseValprzypisaniem, nawet jeśli test byłby prawdziwy.
Bachsau

jest ładnie krótki, ale również bardzo trudny do bezpiecznego użycia jako „zalecany wzorzec”, patrz powyższy komentarz Bachsau ... (więc go przegłosowałem)
tverrbjelke

6

Nie. Myślę, że miałeś nadzieję, że coś takiego num1 = 20 if someBoolValuezadziała, ale tak nie jest. Myślę, że najlepszym sposobem jest ifstwierdzenie, które napisałeś:

if someBoolValue:
    num1 = 20

5
num1 = 10 + 10*(someBoolValue is True)

To moja nowa ostateczna odpowiedź. Wcześniejsza odpowiedź była następująca i była przesada w przypadku podanego problemu. Getting_too_clever == not Good. Oto wcześniejsza odpowiedź ... nadal dobra, jeśli chcesz dodać jedną rzecz do Truewarunku, a drugą do False:

num1 = 10 + (0,10)[someBoolValue is True]

Wspomniałeś, num1że miałby już wartość, którą należy zostawić w spokoju. Założyłem, num1 = 10że to pierwsza wypowiedź postu, więc operacja, do której należy się dostać, 20to dodanie 10.

num1 = 10
someBoolValue = True

num1 = 10 + (0,10)[someBoolValue is True]

print(f'num1 = {num1}\nsomeBoolValue = {someBoolValue}')

wyprodukował ten wynik

num1 = 20
someBoolValue = True

Teraz myślę, że powinienem był odpowiedzieć „num1 = 10 + 10 * (someBoolValue == True)” Problem zdefiniowany jako warunek „Fałsz” w zasadzie „no-op”. Jeśli musiał to być wybór polegający na dodaniu innej wartości dla „Fałsz”, wtedy wcześniejsza odpowiedź jest lepsza. Czy edytuję swój post czy robię to w komentarzach?
MikeyB


2

Jeśli chcesz wywołać metodę, jeśli jakaś wartość logiczna jest prawdziwa, możesz else Nonezakończyć działanie trójnika.

>>> a=1
>>> print(a) if a==1 else None
1
>>> print(a) if a==2 else None
>>> a=2
>>> print(a) if a==2 else None
2
>>> print(a) if a==1 else None
>>>

1

Jeśli na pewno wydarzy się jeden wiersz kodu, Python 3.8 wprowadza wyrażenia przypisania, pieszczotliwie zwane „operatorem morsa”.

:=

someBoolValue and (num := 20)

20Zostanie przypisany numjeśli pierwsze wyrażenie logiczne jest True. Przypisanie musi znajdować się tutaj w nawiasach, w przeciwnym razie wystąpi błąd składni.

num = 10
someBoolValue = True

someBoolValue and (num := 20)
print(num) # 20

num = 10
someBoolValue = False

someBoolValue and (num := 20)
print(num) # 10

0

Dla przyszłych podróżników w czasie z Google, oto nowy sposób (dostępny od Pythona 3.8 i nowszych):

b = 1
if a := b:
    # this section is only reached if b is not 0 or false.
    # Also, a is set to b
    print(a, b)


-1

Oto, co mogę zasugerować. Użyj innej zmiennej, aby wyprowadzić klauzulę if i przypisz ją do num1.

Kod:

num2 =20 if someBoolValue else num1
num1=num2


-1

Możesz to zrobić w ten sposób.

try:
    a = [i for i in [20] if False][0]
except IndexError:
    print("Do what ever you want here")

Możesz rozwiązać swój problem w ten sposób, ale użycie „try / except block” nie jest najlepszą praktyką w Pythonie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.