Поставлення оператора 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

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"

1
"pos"це не твердження, це вираз.
Тім Піцкер

@TimPietzcker Спасибі, я оновив пост, щоб бути більш точним.
Лича

20

Просто вставте інше, якщо в іншому твердженні є пункт. Але це не робить його красивішим.

>>> 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)

насправді ви можете гніздити їх до нескінченності. Насолоджуйтесь;)


як щодо часу, який зайняли? що я думаю, ці мути-петлі будуть забирати набагато більше часу. тож чи може бути альтернатива вкладеним петлям для кращої швидкості споживання.
loveR

привіт @loveR, це не цикл, це просто вкладене, якщо інше, заява, а для цього незначний час
gustavz

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


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()
...

2

Люди вже згадували потрійні вирази. Іноді при простому умовному призначенні в якості прикладу можна використовувати математичний вираз для виконання умовного завдання. Це може не зробити ваш код дуже читабельним, але він отримує його на одному досить короткому рядку. Ваш приклад можна написати так:

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

Порівняння було б істинним чи помилковим, і при множенні чисел тоді було б або 1, або 0. Можна використовувати + замість | посередині.


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

0

Ви можете використовувати вкладені потрійні, якщо заяви.

# 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))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.