Приоритет оператора Python с расширенным присваиванием, включая последовательность

В продолжение моего предыдущего вопроса у меня следующий. Это то же самое в Python?

a += b[1] / 2

а также

a += (b[1] / 2)

При условии что:

  • a ранее был определен как float
  • b это список кортежей
  • b[1] это кортеж с одним элементом

Точно так же мне было бы интересно узнать также поведение, если:

  • a ранее был определен как float
  • b список поплавков

1 ответ

Решение

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

Если мы посмотрим на грамматику, мы увидим:

expr: xor_expr ('|' xor_expr)*
xor_expr: and_expr ('^' and_expr)*
and_expr: shift_expr ('&' shift_expr)*
shift_expr: arith_expr (('<<'|'>>') arith_expr)*
arith_expr: term (('+'|'-') term)*
term: factor (('*'|'@'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power
power: atom_expr ['**' factor]
atom_expr: ['await'] atom trailer*
atom: ('(' [yield_expr|testlist_comp] ')' |
       '[' [testlist_comp] ']' |
       '{' [dictorsetmaker] '}' |
       NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME

"Подписка" ([1] в b[1] таким образом, определяется в производственном правиле trailerи если мы посмотрим на грамматику, это может быть только продуктом factor, так что это означает, что / Оператор имеет приоритет над подпиской.

Так что это означает, что:

a += b[1] / 2

эквивалентно:

a += ((b[1]) / 2)

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

>>> (2.0, 4.0) / 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for /: 'tuple' and 'int'

Для numpy массив, однако, это имеет смысл:

>>> from numpy import array
>>> array([2.0, 4.0])/2
array([1., 2.])
Другие вопросы по тегам