"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.