Поместить оператор if-elif-else в одну строку?

125

Я прочитал ссылки ниже, но они не касаются моего вопроса.
Есть ли в Python тернарный условный оператор? (вопрос заключается в сжатии оператора if-else в одну строку)

Есть ли более простой способ написать оператор if-elif-else, чтобы он умещался в одной строке?
Например,

if expression1:
   statement1
elif expression2:
   statement2
else:
   statement3

Или реальный пример:

if i > 100:
    x = 2
elif i < 100:
    x = 1
else:
    x = 0

Я просто чувствую, что если бы приведенный выше пример можно было бы написать следующим образом, он мог бы выглядеть более кратким.

x=2 if i>100 elif i<100 1 else 0 [WRONG]
Мэтт Элсон
источник

Ответы:

186

Нет, это невозможно (по крайней мере, с произвольными утверждениями) и нежелательно. Размещение всего в одной строке, скорее всего, нарушит PEP-8, где требуется, чтобы длина строк не превышала 80 символов.

Это также противоречит дзену Python: «Читаемость имеет значение». (Введите import thisв командной строке Python, чтобы прочитать все).

Вы можете использовать тернарное выражение в Python, но только для выражений, а не для операторов:

>>> a = "Hello" if foo() else "Goodbye"

Редактировать:

Ваш измененный вопрос теперь показывает, что три утверждения идентичны, за исключением присвоенного значения. В этом случае цепной тернарный оператор работает, но я все еще думаю, что он менее читабелен:

>>> i=100
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
0
>>> i=101
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
2
>>> i=99
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
1
Тим Пицкер
источник
Почему второе выражение не вернуло 0? i выше 100
AstralWolf 03
6
@AstralWolf: Большое спасибо! Это прекрасно иллюстрирует мысль, которую я пытался сформулировать - связанное троичное выражение возможно, но менее читабельно и, очевидно, легко неправильно понять.
Тим Пицкер,
1
Если вам нужно, чтобы он был более читабельным, вы можете заключить его в скобки, например: a = 1 if i < 100 else (2 if i > 100 else 0)(Не проверено, но я думаю, что он должен работать)
Зак
@TimPietzcker, как бы вы описали разницу между выражениями и операторами?
AsheKetchum
62

Если вам нужны разные выражения только для разных случаев, это может сработать для вас:

expr1 if condition1 else expr2 if condition2 else expr

Например:

a = "neg" if b<0 else "pos" if b>0 else "zero"
Lycha
источник
1
"pos"это не утверждение, это выражение.
Тим Пицкер
@TimPietzcker Спасибо, я обновил пост, чтобы он был точнее.
Lycha
20

Просто вложите еще одно предложение if в оператор else. Но это не делает его красивее.

>>> x=5
>>> x if x>0 else ("zero" if x==0 else "invalid value")
5
>>> x = 0
>>> x if x>0 else ("zero" if x==0 else "invalid value")
'zero'
>>> x = -1
>>> x if x>0 else ("zero" if x==0 else "invalid value")
'invalid value'
Дэвид Лай
источник
1
Для меня это гораздо более читабельно, чем принятый ответ, потому что он поддерживает структуру и концепцию первого предложения; просто дело субъективное.
Ezarate11
12

Несмотря на некоторые другие ответы: ДА, это возможно :

if expression1:
   statement1
elif expression2:
   statement2
else:
   statement3

переводится в следующий лайнер:

statement1 if expression1 else (statement2 if expression2 else statement3)

на самом деле вы можете вкладывать их до бесконечности. Наслаждаться ;)

gustavz
источник
как насчет затраченного времени? что я полагаю, эти мути-петли займут гораздо больше времени. так что может быть альтернатива вложенным циклам для лучшей скорости использования.
loveR
привет @loveR, это не цикл, это просто вложенный оператор if else, и поэтому очень мало времени
Густавз
7

При желании вы можете использовать getметод dict:

x = {i<100: -1, -10<=i<=10: 0, i>100: 1}.get(True, 2)

Вам не нужен getметод, если один из ключей гарантированно оценивает True:

x = {i<0: -1, i==0: 0, i>0: 1}[True]

В идеале должен оцениваться не более одного ключа True. Если оценивается более чем один ключ True, результаты могут показаться непредсказуемыми.

Шейн
источник
4
if i > 100:
    x = 2
elif i < 100:
    x = 1
else:
    x = 0

Если вы хотите использовать вышеупомянутый код в одной строке, вы можете использовать следующее:

x = 2 if i > 100 else 1 if i < 100 else 0

При этом x будет присвоено 2, если i> 100, 1, если i <100 и 0, если i = 100

roshanpoudel
источник
3

Это также зависит от характера ваших выражений лица. Общий совет по другим ответам «не делать этого» вполне применим для общих операторов и общих выражений.

Но если все, что вам нужно, это таблица «отправки», например, вызов другой функции в зависимости от значения данной опции, вы можете поместить функции для вызова в словарь.

Что-то вроде:

def save(): 
   ...
def edit():
   ...
options = {"save": save, "edit": edit, "remove": lambda : "Not Implemented"}

option = get_input()
result = options[option]()

Вместо if-else:

if option=="save":
    save()
...
jsbueno
источник
2

Люди уже упоминали троичные выражения. Иногда с помощью простого условного присваивания в качестве примера можно использовать математическое выражение для выполнения условного присваивания. Это может сделать ваш код не очень удобочитаемым, но он займет одну довольно короткую строку. Ваш пример можно было бы записать так:

x = 2*(i>100) | 1*(i<100)

Сравнение будет True или False, а при умножении на числа будет либо 1, либо 0. Можно использовать + вместо | посередине.

Ant6n
источник
1

Троичный оператор является лучшим способом выражения кратким. Синтаксис такой variable = value_1 if condition else value_2. Итак, для вашего примера вы должны дважды применить тернарный оператор:

i = 23 # set any value for i
x = 2 if i > 100 else 1 if i < 100 else 0
yoelvis
источник
0

Вы можете использовать вложенные тернарные операторы if.

# if-else ternary construct
country_code = 'USA'
is_USA = True if country_code == 'USA' else False
print('is_USA:', is_USA)

# if-elif-else ternary construct
# Create function to avoid repeating code.
def get_age_category_name(age):
    age_category_name = 'Young' if age <= 40 else ('Middle Aged' if age > 40 and age <= 65 else 'Senior')
    return age_category_name

print(get_age_category_name(25))
print(get_age_category_name(50))
print(get_age_category_name(75))
k0L1081
источник