Python lexical analysis - logical line & compound statements
所以我明白:
The end of a logical line is represented by the token NEWLINE
这意味着定义python语法的方式结束逻辑行的唯一方法是使用
物理行(而不是eol,它是您在编写文件时使用的平台的eol,但仍然通过python转换为通用的
逻辑行可以或不能等同于一个或多个物理行,但通常它是一个,而且大多数情况下,如果编写干净的代码,它就是一个。
在这个意义上:
1 2 3 4 5 6 7 8 9 | foo = 'some_value' # 1 logical line = 1 physical foo, bar, baz = 'their', 'corresponding', 'values' # 1 logical line = 1 physical some_var, another_var = 10, 10; print(some_var, another_var); some_fn_call() # the above is still still 1 logical line = 1 physical line # because ; is not a terminator per se but a delimiter # since Python doesn't use EBNF exactly but rather a modified form of BNF # p.s one should never write code as the last line, it's just for educational purposes |
不显示1逻辑如何等价于1物理的示例,我的问题是来自文档的以下部分:
Statements cannot cross logical line boundaries except where NEWLINE
is allowed by the syntax (e.g., between statements in compound
statements)
但这甚至意味着什么?我理解复合语句的列表,即它们:if、while、for等。它们都由一个或多个子句组成,而每个子句又由一个标题和一个套件组成。该套件由一个或多个语句组成,让我们以一个更具体的示例为例:
所以根据语法,if语句是这样的(不包括elifs和else子句):
1 | if_stmt ::= "if" expression":" suite |
如果套房及其后续声明:
1 2 3 | suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT statement ::= stmt_list NEWLINE | compound_stmt stmt_list ::= simple_stmt (";" simple_stmt)* [";"] |
这意味着,如果你想,你可以选择(由""给出)你的套房是两种方式之一:
在同一行:
缺点:不是pythonic,并且不能有其他引入新块的复合语句(如func def、其他if等)
宣传:我想是一行
例子:
1 | if 'truthy_string': foo, bar, baz = 1, 2, 3; print('whatever'); call_some_fn(); |
引入新块:
优点:所有,以及正确的方法
例子:
1 2 3 4 5 6 | if 'truthy_value': first_stmt = 5 second_stmt = 10 a, b, c = 1, 2, 3 func_call() result = inception(nested(calls(one_param), another_param), yet_another)) |
但我不明白
Statements cannot cross logical line boundaries except where NEWLINE
is allowed by the syntax
我在上面看到的是一个套件,它是由if子句控制的代码块,反过来,这个套件由逻辑独立的行(语句)组成,其中每个逻辑行都是一个物理行(巧合)。我不明白一条逻辑线是如何跨越界限的(基本上只是一个结尾的花哨词,界限,即换行符),我不明白一条语句是如何跨越这些界限,跨入下一条语句,或者我真的很困惑,把所有的事情都搞混了,但是如果有人能解释的话。
感谢您提前抽出时间。
Python语法
幸运的是,Python文档中有完整的语法规范。
该规范中的语句定义为:
1 | stmt: simple_stmt | compound_stmt |
逻辑行由
好吧,我们来看看这个,A的规格是什么
1 2 3 | 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) |
好吧,现在它进入了几个不同的路径,并且可能没有意义单独地通过所有路径,但是根据规范,如果任何一个
除此之外,只有理论上的可能性
1 2 3 4 5 | compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt [...] if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] [...] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT |
我只选择了
1 2 3 | if 1: 100 200 |
将是:
1 2 3 4 5 6 7 8 9 | if_stmt |---> test --> 1 |---> NEWLINE |---> INDENT |---> expr_stmt --> 100 |---> NEWLINE |---> expr_stmt --> 200 |---> NEWLINE |---> DEDENT |
所有这些都属于if语句(它不仅仅是由
一种可视化的方法是使用内置的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import symbol import parser import token s =""" if 1: 100 200 """ st = parser.suite(s) def recursive_print(inp, level=0): for idx, item in enumerate(inp): if isinstance(item, int): print('.'*level, symbol.sym_name.get(item, token.tok_name.get(item, item)), sep="") elif isinstance(item, list): recursive_print(item, level+1) else: print('.'*level, repr(item), sep="") recursive_print(st.tolist()) |
实际上,我不能解释大多数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | file_input .stmt ..compound_stmt ...if_stmt ....NAME ....'if' ....test .........expr ...................NUMBER ...................'1' ....COLON ....suite .....NEWLINE .....INDENT .....stmt ...............expr .........................NUMBER .........................'100' .......NEWLINE .....stmt ...............expr .........................NUMBER .........................'200' .......NEWLINE .....DEDENT .NEWLINE .ENDMARKER |
这可能会变得更漂亮,但我希望它可以作为说明,即使在它的当前形式。
比你想象的简单。复合语句被视为单个语句,即使其中可能包含其他语句。引用文档:
Compound statements contain (groups of) other statements; they affect or control the execution of those other statements in some way. In general, compound statements span multiple lines, although in simple incarnations a whole compound statement may be contained in one line.
例如,
1 2 3 | if a < b: do_thing() do_other_thing() |
是一个单