"elif" у списку умовами розуміння


129

Чи можемо ми використовуватись elifу розумінні списку?

Приклад:

l = [1, 2, 3, 4, 5]

for values in l:
    if values==1:
        print 'yes'
    elif values==2:
        print 'no'
    else:
        print 'idle'

Чи можемо ми включити до elifнашого списку розуміння аналогічно наведеному вище коду?

Наприклад, відповідь на зразок:

['yes', 'no', 'idle', 'idle', 'idle']

До сих пір я використовував лише ifта elseв розумінні списку.

Відповіді:


250

Умовні вирази Python були розроблені саме для такого випадку використання:

>>> l = [1, 2, 3, 4, 5]
>>> ['yes' if v == 1 else 'no' if v == 2 else 'idle' for v in l]
['yes', 'no', 'idle', 'idle', 'idle']

Сподіваюсь, це допомагає :-)


5
У синтаксисі є якась цікава історія. Протягом багатьох років перед їх введенням «третинні вирази» були однією з п’яти найбільш запитуваних змін у мові. Оскільки Гвідо ван Россум явно розробив це як мову, засновану на твердженнях, він довго наполегливо чинив опір (третинні вирази, особливо їх зловживання, є джерелом великої неясності в коді). Коли він нарешті піддався, він оголосив, що навмисно обрав синтаксис, який відмовляв від зайвого використання. Як завжди, він все-таки зробив елегантну дизайнерську роботу.
holdenweb

1
Тернар, чорт забирай (він писав, помічаючи свою дислексичну помилку занадто пізно, щоб редагувати).
holdenweb

2
Хоча я голосую за цю відповідь, я хочу зазначити це: для 1 пари if / else легко читати, 2 пари: зрозуміти це стає важче. Навіть не згадуйте 3 пари. Якщо вираз потребує 3 і більше пар, словник або окрема функція полегшать читання та розуміння.
Хай Ву

1
Я хотів би додати не рішення цієї проблеми, а нагадування про чистий код: оскільки розуміння цього списку має три умови, воно, ймовірно, може бути перероблене на більш описовий метод. Моя думка така: martinfowler.com/bliki/FunctionLength.html :)
Альваро Кавальканті

Я натрапив на випадок, коли мені потрібен еліф, але лише два значення. Використовуючи цей приклад, мені потрібно було б просто ['yes', 'no']зробити. Щоб зробити це, ви можете зробити: ['yes' if v == 1 else 'no' for v in l if values in [1,2]]. Наразі я не можу придумати більш чистий спосіб зробити це.
dTanMan

48
>>> d = {1: 'yes', 2: 'no'}
>>> [d.get(x, 'idle') for x in l]
['yes', 'no', 'idle', 'idle', 'idle']

4
Я думаю, що цю форму набагато легше засвоювати, ніж намагатися зробити дійсно довгу і складну, якщо логіка в іншому списку
jdi

5
@jdi Хоча умовні вирази можуть не на ваш смак, вони були спеціально розроблені для обробки ланцюгів if-elif-elif-else, як того вимагала ОП. Вони не важко вчитися і можуть коректно обробляти ситуації, які не як піддається словник логіки пошуку: 'A' if grade>=90 else 'B' if grade>=80 else 'C' if grade>=70 else 'F'.
Реймонд Хеттінгер

1
Якщо є перевага визначення dпоза розумінням?
Chris_Rands

Причина, якою мені подобається розуміння списку, полягає в тому, що він читається так само, як англійська. Навіть непрограміст міг би зрозуміти, що це робить. За допомогою цього рішення ви повинні зрозуміти метод dict.get ().
Тім Сков Якобсен

26

Можна, начебто.

Зауважте, що коли ви використовуєте sytax, наприклад:

['yes' if v == 1 else 'no' for v in l]

Ви використовуєте потрійну форму оператора if / else (якщо ви знайомі з такими мовами, як C, це як ?:конструкт (v == 1 ? 'yes' : 'no'):).

У потрійній формі оператора if / else не вбудований 'elif', але ви можете імітувати його в умовах 'else':

['yes' if v == 1 else 'no' if v == 2 else 'idle' for v in l]

Це як сказати:

for v in l:
    if v == 1 :
        print 'yes'
    else:
        if v == 2:
            print 'no'
        else:
            print 'idle'

Таким чином, немає прямої конструкції "elif", як ви просили, але вона може бути змодельована вкладеними операторами if / else.


1
Останній код абзацу дуже проникливий!
devianceee


2

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

>>> l = [1, 2, 3, 4, 5]
>>> result_map = {1: 'yes', 2: 'no'}
>>> [result_map[x] if x in result_map else 'idle' for x in l]
['yes', 'no', 'idle', 'idle', 'idle']

2

Ще один простий спосіб - використовувати умовне розуміння списку таким чином:

l=[1,2,3,4,5]
print [[["no","yes"][v==1],"idle"][v!=1 and v!=2] for v in l]

дає правильну відповідь:

["так", "ні", "простоювати", "простоювати", "простоювати"]

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