Приоритет оператора Python - PullRequest
9 голосов
/ 25 июля 2010

Документы Python говорят, что * и / имеют одинаковый приоритет.
Я знаю, что выражения в Python вычисляются слева направо.

Могу ли я полагаться на это и предположить, что j j/ m всегда равно (j j) / m, избегая скобок?
Если это так, могу ли я считать, что это верно для операторов с одинаковым приоритетом в целом?


ps: вопрос, как он подходит для моих целей, я пришел к нему, читая только целочисленный код (как в приведенном выше примере) без скобок, что в то время показалось мне довольно подозрительным.

Ответы [ 3 ]

14 голосов
/ 25 июля 2010

Да - разные операторы с одинаковым приоритетом левоассоциативны;то есть будут обрабатываться два крайних левых элемента, затем результат и третий элемент и т. д.

Исключением является оператор **:

>>> 2 ** 2 ** 3
256

Кроме того,операторы сравнения (==, > и т. д.) не ведут себя ассоциативно, а вместо этого переводят x [cmp] y [cmp] z в (x [cmp] y) and (y [cmp] z).

13 голосов
/ 25 июля 2010

Но, если это неоднозначно для вас - кодера - и это должно быть потому, что вы должны спросить, тогда ожидайте, что это будет по крайней мере столь же неоднозначно для читателя и потратите пару октетов для ясности.

Полагаться на правила приоритетов - это здорово, если вы оказались компилятором.

добавлены ответы на комментарии :

Для человека, читающего код, который сталкивается с неоднозначностью, требующей внешних консультаций для уверенности, вы должны предположить, что следующий читатель будет менее опытнымчем вы и сэкономить им усилия и избежать человеческой ошибки разбора той же конструкции и добавить скобки для них.

Так получилось, что даже принятый ответ был неверным (обоснование, а не эффект, см. Его первый комментарий), о котором я не знал, и ни одна не была частью тех, кто проголосовал за него.

Что касается утверждения об основной алгебре, то конкретный пример, используемый в ОП, поучителен.Независимо от приоритета оператора выражение j * (j / m) алгебраически идентично (j * j) / m.К сожалению, алгебра Питона является лишь приближением алгебры «платоновского идеала», которая может дать неправильные ответы для любой формы в зависимости от величин j и m.Например:

>>> m = 1e306
>>> m
1e+306
>>> j = 1e307
>>> j
9.9999999999999999e+306
>>> j / m
10.0
>>> j*j
inf
>>> j * (j / m)
1e+308
>>> (j * j) / m
inf
>>> ((j * j) / m) == (j * (j/m))
False

Таким образом, свойство тождества квазиалгебры Python (и моего FPU) не выполняется.И это может отличаться на вашем компьютере, так как примечания к документации :

Числа с плавающей запятой реализованы с использованием двойного в C. Все ставки на их точность отключены, если вы не случайнознать машину, с которой вы работаете.

Можно утверждать, что никто не имеет дела с волосатыми краями переполнения, и это в некоторой степени верно, но удалено из контекста, выражение является неопределенным, учитываяодин порядок операций и «правильный» под другой.

3 голосов
/ 25 июля 2010

Краткий ответ: да.

Документация Python гласит следующее:

Операторы в одном поле имеют одинаковый приоритет.Если синтаксис не указан явно, операторы являются двоичными.Операторы в той же группе блоков слева направо (за исключением сравнений, включая тесты, у которых все имеют одинаковый приоритет и цепочку слева направо ... и возведения в степень, которые группируются справа налево).

Таким образом, другими словами, ответ на ваш вопрос - да, операторы с одинаковым приоритетом сгруппируют слева направо отдельно от Сравнений, которые цепочка , а не группа :

>>> x = 0
>>> y = 0
>>> x == y == True
False
>>> (x == y) == True
True
>>> x == (y == True)
True

и экспонента:

>>> 2 ** 2 ** 3
256
>>> (2 ** 2) ** 3
64
>>> 2 ** (2 ** 3)
256

Кроме того, в назначении правая часть оценивается перед левой частью:

>>> x = 1
>>> y = x = 2
>>> y
2
...