Саморегуляторный троичный

Я делал это некоторое время:

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

Вернуться к моему основному вопросу: не беспокойтесь об этом. Используйте то, с чем вам удобно.