Рейтинг@Mail.ru

Python: Маленькая хитрость. if-else vs and-or.


На этот раз будет мини-заметка, уж слишком мне понравился трюк, о котором пойдёт речь дальше :).

Наверное любому программисту приходится часто писать конструкции такого вида:

if a == b:
    c = d
else:
    c = e

Как-то разбирая исходники какого-то проекта наткнулся на весьма компактную замену. Вот для сравнения два аналогичных блока кода с использованием логических операций python’а и с использованием конструкции if-else:

# if-else:
if random.random() > 0.5:
    a = 1
else:
    a = 0

# and-or style:
a = random.random() > 0.5 and 1 or 0

На мой взгляд выглядит гораздо лучше и компактнее (да-да, if-else можно записать в 2 строчки вместо 4, но мне так не нравится ^__^) . Другое дело, что некоторым это может показаться противоречиво с некоторыми пунктами дзена python’а (import this), но это спорно :). В общем использую там, где считаю нужным.

Кстати, если кого-то интересует производительность, то она примерно одинакова, далее выложу тесты и объяснение логики для тех, кому интересно.

>>> import timeit
>>> t1 = timeit.Timer('if random.random()>0.5:a=1\nelse:a =0', 'from __main__ import a\nimport random')
>>> t2 = timeit.Timer('a=random.random()>0.5 and 1 or 0', 'from __main__ import a\nimport random')
>>> t1.repeat()
[0.21074632467116317, 0.2097615509806019, 0.20978293771349854]
>>> t2.repeat()
[0.21944338095772764, 0.21785226684687586, 0.21940797240040411]

Тесты привёл, теперь объяснение.

Дело в том, что логические операции and и or в python’е возвращают один из операндов. Операция and возвращает первый операнд, если он приводится к логическому типу False, иначе – второй. Операция or наоборот, возвращает 1й операнд, если он приводится к типу True, иначе – второй. Всё это связано с «ленивостью» (lazy) операций, вычисляется столько аргументов, сколько надо для того, чтобы однозначно определить результат (например, 1 or x всегда даёт True, поэтому x не вычисляется).

lizz Программирование, общие вопросы ,

Пожалуйста, оцените полезность и качество данной статьи. Одна звезда - плохо, 5 - хорошо.
1 звезда2 звезды3 звезды4 звезды5 звёзд (Еще не оценили)
Loading ... Loading ...

  1. Сергей
    20 Май 2010 в 16:20 | #1

    Не следует забывать о том, что вот такая конструкция отработает правильно:
    a = random.random() > 0.5 and 1 or 0

    А вот такая конструкция всегда будет возвращать устанавливать a=1
    a = random.random() <= 0.5 and 0 or 1

  2. 20 Май 2010 в 22:05 | #2

    @Сергей
    Верно, для этого я кратко написал про ленивость операций, но спасибо за замечание. Просто увидев такой вариант был сильно удивлён что до такого кто-то додумался :).

    Да и злоупотреблять такими конструкциями тоже не стоит, они сокращают код, но понижают его читаемость :), это всё же именно «трюк».

    Но если задача будет примерно такой: http://clck.ru/0faG то это будет отличный вариант).

  1. Пока что нет уведомлений.