Ошибка синтаксиса выражений присваивания Python

avatar
Abhijit Sarkar
8 августа 2021 в 23:14
67
1
-1

Используя Python 3.9, у меня есть функция, которая возвращает tuple[float, float] следующим образом:

return slope := _slope(c1, c2), _y_intercept(c1, slope)

Я использую выражение присваивания, определенное в PEP 572.

Но это выдает следующую ошибку:

test_moderate.py:None (test_moderate.py)
../../venv/lib/python3.9/site-packages/_pytest/python.py:578: in _importtestmodule
    mod = import_path(self.fspath, mode=importmode)
../../venv/lib/python3.9/site-packages/_pytest/pathlib.py:524: in import_path
    importlib.import_module(module_name)
/Users/me/.pyenv/versions/3.9.2/lib/python3.9/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1030: in _gcd_import
    ???
<frozen importlib._bootstrap>:1007: in _find_and_load
    ???
<frozen importlib._bootstrap>:986: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:680: in _load_unlocked
    ???
../../venv/lib/python3.9/site-packages/_pytest/assertion/rewrite.py:170: in exec_module
    exec(co, module.__dict__)
test_moderate.py:4: in <module>
    from moderate import functions as func
E     File "/moderate/functions.py", line 346
E       return slope := _slope(c1, c2), _y_intercept(c1, slope)
E                    ^
E   SyntaxError: invalid syntax
collected 0 items / 1 error
Источник
Karl Knechtel
8 августа 2021 в 23:18
0

Если вы return на этой линии, то назначение, безусловно, не имеет смысла. Просто return выражение.

Karl Knechtel
8 августа 2021 в 23:20
0

В любом случае, вы не задали вопрос, и на ваш подразумеваемый вопрос дан ответ <49905555552766> в ссылке, которую вы дали : «Выражения присваивания без скобок запрещены в качестве аннотаций для аргументов, возвращаемых значений и присваиваний».

juanpa.arrivillaga
8 августа 2021 в 23:23
0

Наверное нужно добавить скобки

Abhijit Sarkar
8 августа 2021 в 23:24
0

Причина, по которой я не добавил круглые скобки, заключается в том, что PyCharm показывает предупреждение о «избыточных скобках», но ошибка исчезает.

Ответы (1)

avatar
Carcigenicate
8 августа 2021 в 23:20
1

Вам нужно обернуть это выражение в ():

return (slope := _slope(c1, c2), _y_intercept(c1, slope))

Я предполагаю, что ваш код анализировался примерно так:

return slope (:= _slope(c1, c2), _y_intercept(c1, slope))

Что не имеет смысла. Если вы сомневаетесь, заключите выражение в скобки и посмотрите, изменит ли это поведение. Если да, то, скорее всего, проблема в приоритете.


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

Глядя на грамматику Python, это может быть связано с тем фактом, что return определяется как принимающее форму:

return_stmt:
    | 'return' [star_expressions]

star_expressions:
    | star_expression (',' star_expression )+ [','] 
    | star_expression ',' 
    | star_expression

star_expression:
    | '*' bitwise_or 
    | expression

И := вводит named_expression, а не star_expressions:

named_expression:
    | NAME ':=' ~ expression 
    | expression !':='

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

Abhijit Sarkar
8 августа 2021 в 23:24
0

Причина, по которой я не добавил круглые скобки, заключается в том, что PyCharm показывает предупреждение о «избыточных скобках», но ошибка исчезает.

Carcigenicate
8 августа 2021 в 23:25
1

@AbhijitSarkar К сожалению, Pycharm дает несколько плохих предупреждений. Это отличный инструмент, но он не идеален.

Abhijit Sarkar
9 августа 2021 в 00:15
0

FWIW, помещая # noinspection PyRedundantParentheses в метод, подавляет предупреждения. Другой вариант — добавить встроенный #noqa.

Carcigenicate
9 августа 2021 в 00:20
0

@AbhijitSarkar Это может отключить предупреждение, но я думаю, что это ошибка, которую следует исправить. Это либо «ошибка» в спецификации грамматики (маловероятно), либо в линтере Pycharm (более вероятно, поскольку это своего рода странный угловой случай). Если в какой-то момент у меня будет время, я могу сообщить об этом в Jetbrains. Вы могли бы также, если у вас есть возможность.

Carcigenicate
9 августа 2021 в 00:24
0

Я не могу понять, почему := может вызвать проблемы в этом контексте, помимо того факта, что это кажется плохой практикой и немного бессмысленным (я предполагаю, что вы переназначали глобальное значение?). Кажется, что это можно «исправить», просто определив новое правило как что-то вроде return_expression: | named_expression | star_expressions, а затем выполнив return_stmt: | 'return' [return_expression]. Это может показаться настолько бесполезным случаем, что оно не стоит изменений.