所以我理解:
逻辑行的结尾由令牌NEWLINE
表示
这意味着定义Python语法的方式是结束逻辑行的唯一方法是使用\n
令牌。
物理线也是如此(相当于EOL,这是您在编写文件时使用的平台的EOL,但仍然被Python转换为通用\n
。
逻辑行可以或不可以等同于一个或多个物理行,但通常只有一行,如果你编写干净的代码,大多数时候都是一行。
从某种意义上说:
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个实体,我的问题是文档中的以下部分:
除NEWLINE之外,语句不能跨越逻辑行边界 语法允许(例如,在复合语句之间) 语句)
但这甚至意味着什么?我理解复合语句的列表,如下: if,while,for,等等,它们都由一个或多个子句和每个子句组成反过来由标题和套件组成。 套件由一个或多个语句组成,让我们举一个更具体的例子:
所以 if语句根据语法(不包括elifs和else子句):
if_stmt ::= "if" expression ":" suite
套件及其后续陈述:
suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement ::= stmt_list NEWLINE | compound_stmt
stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
所以这意味着如果你想要你可以选择(由“|”给出)你的套房是2种方式之一:
在同一行:
缺点:不是pythonic,你不能有另一个引入新块的复合语句(如func def,另一个if等)
advatanges :我猜是一个班轮
示例:
if 'truthy_string': foo, bar, baz = 1, 2, 3; print('whatever'); call_some_fn();
引入一个新块:
优势:全部,以及正确的方法
示例:
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))
但我不知道如何
除NEWLINE之外,语句不能跨越逻辑行边界 语法
允许
我在上面看到的是套件,这是一个由 if子句控制的代码块,反过来,< strong> suite ,由逻辑的,独立的行(语句)组成,其中每条逻辑行是一条物理行(巧合)。我没有看到一条逻辑线如何跨越边界(这基本上只是结尾的一个奇特的词,限制,这是换行符),我看不出一个语句如何跨越这些边界并跨越到下一个声明,或者我真的很困惑,一切都搞砸了,但如果有人可以请解释。
感谢您提前抽出时间。
答案 0 :(得分:4)
幸运的是,Python文档中有Full Grammar specification。
声明在该规范中定义为:
stmt: simple_stmt | compound_stmt
逻辑行由NEWLINE
分隔(这不在规范中,但基于您的问题)。
好的,让我们来看看,
的规范是什么simple_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)
好了,现在它进入了几个不同的路径,单独遍历所有路径可能没有意义,但基于规范,simple_stmt
可以跨越逻辑行边界< em> if small_stmt
中的任何一个NEWLINE
包含compound_stmt
(目前他们不但可以)。
除了理论上的可能性之外,实际上还有
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
if
我只选择了suite
语句和if
,因为它已经足够了。 elif
语句包括 else
和NEWLINE
以及其中的所有内容都是一个语句(复合语句)。因为它可能包含suite
s(如果simple_stmt
不仅仅是if
),它已经满足了“跨越逻辑行边界的语句”的要求。
if 1:
100
200
(示意图):if_stmt
|---> test --> 1
|---> NEWLINE
|---> INDENT
|---> expr_stmt --> 100
|---> NEWLINE
|---> expr_stmt --> 200
|---> NEWLINE
|---> DEDENT
将是:
if
所有这些都属于if语句(并且它不仅仅是由while
或if
“控制”的块,...)。
parser
,symbol
和token
parser
可视化的方法是使用内置的token
,symbol
和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())
模块(实际上,在我写答案之前我还不知道这个模块) :
parser
实际上我无法解释大部分suite
结果,但它显示(如果删除了很多不必要的行),if_stmt
包含它的换行符确实属于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
。缩进表示解析器在特定点的“深度”。
{{1}}
这可能会变得更加美丽,但我希望它可以作为插图,即使它的当前形式也是如此。
答案 1 :(得分:2)
这比你想象的要简单。复合语句被视为单个语句,即使它可能包含其他语句。引用docs:
复合语句包含(组)其他语句;它们以某种方式影响或控制其他陈述的执行。 通常,复合语句跨越多行,但在简单的化身中,整个复合语句可能包含在一行中。
例如,
-u
是一个占用3条逻辑行的if a < b:
do_thing()
do_other_thing()
语句。这就是语句如何跨越逻辑行边界。