
python语言的语法由backus-naur form (bnf) 或其扩展形式(如ebnf)精确定义,这为我们理解语言的结构提供了基础。对于赋值语句,python官方文档给出了如下核心bnf规则:
assignment_stmt ::= (target_list "=")+ (starred_expression | yield_expression)
target_list ::= target ("," target)* [","]
target ::= identifier
| "(" [target_list] ")"
| "[" [target_list] "]"
| attributeref
| subscription
| slicing
| "*" target其中,赋值语句的右侧(RHS)必须是starred_expression或yield_expression。它们的定义如下:
starred_expression ::= expression | (starred_item ",")* [starred_item]
starred_item ::= assignment_expression | "*" or_expr
yield_atom ::= "(" yield_expression ")"
yield_expression ::= "yield" [expression_list | "from" expression]初次接触时,我们可能会对一个看似简单的赋值语句,例如a = 9,感到困惑。问题在于,赋值操作符=右侧的字面量9,如何能够匹配到starred_expression或yield_expression这些更复杂的语法结构中?尤其是yield_expression明显与生成器相关,而starred_expression中的*通常用于解包操作。
解答这个困惑的关键在于starred_expression的第一个产生式:
starred_expression ::= expression | (starred_item ",")* [starred_item]
这表明,一个starred_expression可以仅仅是一个expression。换句话说,任何被Python语法定义为“表达式”的内容,都可以合法地出现在赋值语句的右侧,作为starred_expression的一种简单形式。因此,问题现在转化为:数字字面量9是如何被归类为expression的?
立即学习“Python免费学习笔记(深入)”;
要理解9如何成为一个expression,我们需要沿着BNF规则从expression向下追溯,直到找到能够匹配9的终结符。这个追溯路径非常长,但每一步都是逻辑自洽的:
starred_expression ::= expression | (starred_item ",")* [starred_item]
expression ::= conditional_expression | lambda_expr
conditional_expression ::= or_test ["if" or_test "else" expression]
or_test ::= and_test | or_test "or" and_test
and_test ::= not_test | and_test "and" not_test
not_test ::= comparison | "not" not_test
comparison ::= or_expr (comp_operator or_expr)*
or_expr ::= xor_expr | or_expr "|" xor_expr
xor_expr ::= and_expr | xor_expr "^" and_expr
and_expr ::= shift_expr | and_expr "&" shift_expr
shift_expr ::= a_expr | shift_expr ("<<" | ">>") a_expr
a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr
m_expr ::= u_expr | m_expr "*" u_expr | m_expr "@" m_expr |
m_expr "//" u_expr | m_expr "/" u_expr |
m_expr "%" u_expr
u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr
power ::= (await_expr | primary) ["**" u_expr]
primary ::= atom | attributeref | subscription | slicing | call
atom ::= identifier | literal | enclosure
literal ::= stringliteral | bytesliteral
| integer | floatnumber | imagnumber
integer ::= decinteger | bininteger | octinteger | hexinteger
decinteger ::= nonzerodigit (["_"] digit)* | "0"+ (["_"] "0")*
nonzerodigit ::= "1"..."9"从上述BNF链条中我们可以清晰地看到:
因此,9通过这一系列递归的BNF规则,最终被成功地归类为expression,进而满足了starred_expression的要求。
这个追溯过程之所以能够成立,一个非常重要的原因在于BNF规则中广泛存在的“可选性”。在BNF中,方括号[]表示其内部的元素是可选的。这意味着许多非终结符(non-terminal)的定义,即使看起来描述的是带有操作符或特定结构的复杂表达式,也允许其以最简单的形式存在。
例如:
正是这种“可选性”的机制,使得一个简单的字面量9能够向上层层匹配,满足所有中间非终结符的最低要求,最终被识别为一个完整的expression。
理解BNF的这种结构对于深入掌握Python语法至关重要。例如:
# 9 是一个 expression,也是一个 starred_expression
a = 9
# 9 + 5 也是一个 expression,因为它符合 a_expr 规则
b = 9 + 5
# "hello" 字符串字面量也是一个 expression
c = "hello"
# 一个函数调用也是一个 primary,因此也是一个 expression
def greet():
return "Hi"
d = greet()
# 即使是更复杂的条件表达式,如果没有 if/else 部分,也仍然是 expression
# 例如,这里的 `True` 本身就是一个 expression (通过 atom -> literal -> identifier)
e = True注意事项:
通过对Python赋值语句及其相关BNF规则的深入分析,我们明白了a=9中数字字面量9之所以能够作为赋值语句右侧的合法内容,是因为它通过starred_expression可作为expression的规则,并沿着expression到literal的完整BNF推导链,最终被识别为一个整数integer。这个过程的关键在于BNF规则中广泛存在的可选性,它允许简单的元素通过满足最低要求来匹配更复杂的语法结构。理解这些BNF规则不仅能帮助我们更透彻地理解Python的语法结构,也为我们分析和构建更复杂的语言工具提供了基础。
以上就是深入理解Python赋值语句的BNF语法结构的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号