Саморегуляторный троичный
Я делал это некоторое время:
x = x if x else y
Во всех контекстах, где x может быть None
, False
, 0
, ''
, []
или {}
.
Я знаю, что пуристы предпочли бы я:
if not x:
x = y
но забывайте, что это не мой вопрос. Мой вопрос:
Есть ли что-то "неправильное" с x = x if x else y
, кроме того, что это тройной? В частности, нормально ли иметь тернарную самопривязку.
Примечание
Мой qustion не есть x = x if C else y
ok. Я знаю, что это так.
Большое спасибо
Ответы
Ответ 1
Нет ничего плохого в использовании тернарного для x = x if c else y
, однако в случае x = x if x else y
логика действительно просто сводится к
x = x or y
Это связано с тем, что в Python x or y
вычисляется ', если x является ложным, тогда y, else x'
Итак x if x else y
== y if not x else x
== x or y
Очевидно, что x or y
является самым ясным и должен использоваться.
Ответ 2
Нет, ничего страшного в этом.
На самом деле это очень pythonic. Я помню, что читал, что предпочтительный (сам Гвидо) тройной эквивалент. Я посмотрю, смогу ли я выкопать ссылку.
Лично я считаю другой способ более читабельным, но вы не просили моего личного мнения.;)
UPDATE:
Вот цитата.
Core Python Programming, 2nd ed.; Уэсли Дж. Хун; Prentice Hall 2007
Если вы приехали из мира C/С++ или Java, трудно игнорировать или преодолевать тот факт, что у Python не было условного или тройного оператора (C? X: Y) в течение самого длинного времени. [...] Гвидо сопротивлялся добавлению такой функции в Python из-за его веры в простой код и не дает программистам простых способов обфускации их код. Однако, спустя более десятилетия, он дал, в основном из-за подверженных ошибкам способов, с помощью которых люди пытались имитировать его с помощью и/или - или несколько раз неправильно. В соответствии с Часто задаваемые вопросы, один из способов правильного выбора - это (C и [X] или [Y]) [0]. единственная проблема заключалась в том, что сообщество не могло согласиться с синтаксисом. (Вам действительно нужно взглянуть на PEP 308, чтобы увидеть все разные предложения.) Это одна из областей Python, в которой люди выражали сильные чувства. Окончательное решение пришло к Guido выбирая наиболее предпочтительные (и самые любимые) из всех вариантов, затем применяя его к различным модулям в стандартной библиотеке. В соответствии для ОПТОСОЗ ", этот обзор приближает выборку использования в реальном мире случаев в различных приложениях, написанных рядом программисты с разнообразным фоном". И это синтаксис, который был наконец, выбран для интеграции в Python 2.5: X, если C else Y.
Ответ 3
С точки зрения дизайна языка ничего не происходит. Как упоминалось еще один плакат, это даже самый предпочтительный способ. Я даже спросил бы вас, почему вы подразумеваете, что быть троярем не так?
С точки зрения удобочитаемости/поддерживаемости, вещи немного более гибкие. С одной стороны, если у вас будет много случайных, не-Python читателей/сопровождающих, эта конструкция (в отличие от if not x: x= C
) может быть гораздо менее читаемой. С другой стороны, ваша программа, скорее всего, будет содержать многие другие (и гораздо более глубокие) питонизмы. Вы имеете право ожидать от своих читателей минимум знаний.
С точки зрения производительности x
, являющаяся переменной, обе формы оптимизируются (если не эффективно оптимизированы) различными реализациями в один и тот же код. Не имеет значения в этих терминах.
UPDATE:
Я не знал высказываний Guido по этому вопросу, цитируемым @Edward. Я рад, что он согласен со мной. Или я с ним. Но он был абсолютно прав в отношении введения тернарного оператора, поскольку он намного яснее, чем альтернативы типа x= (x,C)[not x]
или x= x or C
, которые использовались (и продвигались) многими ранними программистами на Python с фоном C (и, возможно, также как "классная", дифференцирующая вещь). Кстати, оба они в целом правильны (в зависимости от точной семантики).
Ответ 4
Я смущаюсь делать это, потому что здесь мое настоящее мнение:
Не микро-оптимизируйте. Используйте то, с чем вам удобно; используйте то, что делает ваш код наиболее читаемым. Тройное утверждение прекрасно, если это то, что вы считаете наиболее читаемым.
Тем не менее,
[email protected]:~$ python3 -m timeit 'x = 1; x=x if x else 2'
10000000 loops, best of 3: 0.0345 usec per loop
[email protected]:~$ python3 -m timeit '''
> x=1
> if not x:
> x=2
> '''
10000000 loops, best of 3: 0.0239 usec per loop
Есть некоторые небольшие накладные расходы при назначении x обратно на себя.
dis.dis(f)
2 0 LOAD_FAST 0 (x)
3 POP_JUMP_IF_FALSE 12
6 LOAD_FAST 0 (x) #this is the extra instruction
9 JUMP_FORWARD 3 (to 15)
>> 12 LOAD_CONST 1 (1)
>> 15 STORE_FAST 0 (x)
18 LOAD_CONST 0 (None)
21 RETURN_VALUE
Вернуться к моему основному вопросу: не беспокойтесь об этом. Используйте то, с чем вам удобно.