社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

带增强赋值的python运算符优先级

Manngo • 5 年前 • 913 次点击  

看来这个问题只对Java进行了回答,但我想知道它在Python中是如何工作的。这些是一样的吗?

a += b / 2

a += (b / 2)
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/30648
 
913 次点击  
文章 [ 2 ]  |  最新文章 5 年前
Willem Van Onsem
Reply   •   1 楼
Willem Van Onsem    5 年前

简短回答 : += 是一个 增量赋值 如果我们考虑到语法,在语法树中解析的语法比一般的运算符(因此 / 尤其是操作员)。

Python看到 += 作为“ 增量赋值 “。如果我们检查 Python grammar 我们看到:

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=')

现在语法也强制 优先规则 解析时。如果我们看看与 stmt (“ 陈述 “”我们看到:

stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
             import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
                     ('=' (yield_expr|testlist_star_expr))*)

详尽地解释所有其他陈述(如 del_statement )会花太长时间,但是 expr_stmt 是唯一一个导致 augassign (和) 增广赋值 是导致 += 令牌)。所以我们可以忽略其他表达式。

如果我们把 EXPRO-STMT 这样它就有了 增广赋值 在里面,我们取回 产生式规则 :

expr_stmt: testlist_star_expr augassign (yield_expr|testlist)

这个 testlist_star_expr 是导致标识符(或序列解包时的多个标识符)等的变量。

在右边我们看到一个 yield_expr ,或者 test_list . 一 测试列表 可能导致逗号分隔的表达式,其中:

testlist: test (',' test)* [',']

这个 test 允许写入三元运算符,但这是 强制性的:

test: or_test ['if' or_test 'else' test] | lambdef

我们可以接受 or_test 变量,用于将表达式与 or 分隔符(也是可选的),因为 具有最高优先级。

or_test: and_test ('or' and_test)*

然后跟随 and_test 顾名思义,这让我们可以写 and 运营商:

and_test: not_test ('and' not_test)*

然后跟随 not 操作员(与 not_test ):

not_test: 'not' not_test | comparison

我们可以有任意数量的 在前面,但最终我们会选择 comparison .

如果我们看一下 比较 我们看到:

comparison: expr (comp_op expr)*

这样就允许 比较器链 ,像 x <= y < z ,接下来我们来看看 expr :

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)*

所以这定义了优先规则,我们看到了 | 优先于 ^ ,优先于 & 等等,直到我们看到 term 是一个序列 factor s与运算符 '*' , '@' , '/' , '%' // 在这里,我们终于“消费”了 * . 这意味着 / 在语法树中低于 += 节点。

因此,python解析此表达式的方式是:

a += (b / 2)
Martijn Pieters
Reply   •   2 楼
Martijn Pieters    5 年前

是的,这些都是一样的。python的增强赋值是 不是表达式 ,它是一个语句,在表达式优先规则中不起作用。 += 不是运算符,而是扩充赋值语句语法的一部分。

所以一切 += 是一个表达式,但是 += 本身不是,所以分配总是最后处理。

而且因为(增广的)赋值不是表达式,它也不能产生一个值来用于周围的表达式。没有 (a += b) / 2 ,这是一个语法错误,当然不是 if (a += b / 2): 或者其他类似的恶作剧。

reference documentation on Augmented assignment statements ,表示语法为:

augmented_assignment_stmt ::=  augtarget augop (expression_list | yield_expression)
augtarget                 ::=  identifier | attributeref | subscription | slicing
augop                     ::=  "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="
                           | ">>=" | "<<=" | "&=" | "^=" | "|="

所以 augop 是语句语法的一部分,只有后面的部分是表达式(特别是 expression_list yield_expression 语法规则)。

此外,解释表明:

增强赋值计算目标(与普通赋值语句不同,它不能是解包语句)和表达式列表,对两个操作数执行特定于赋值类型的二进制操作,并将结果分配给原始目标。目标只评估一次。

所以 augtarget 首先处理部分,然后处理表达式列表(或yield表达式),然后扩展赋值应用运算符并返回结果。

此外,表达式引用文档 does include a precedence table ,但该表不包括赋值(增广或其他),因为赋值不是表达式而是语句。