Python词法分析 - 逻辑线和&复合语句

时间:2018-03-28 08:18:57

标签: python python-3.x python-internals bnf

所以我理解:

  

逻辑行的结尾由令牌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种方式之一:

  1. 在同一行:

    缺点:不是pythonic,你不能有另一个引入新块的复合语句(如func def,另一个if等)

    advatanges :我猜是一个班轮

  2. 示例:

    if 'truthy_string': foo, bar, baz = 1, 2, 3; print('whatever'); call_some_fn();
    
    1. 引入一个新块:

      优势:全部,以及正确的方法

    2. 示例:

      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 ,由逻辑的,独立的行(语句)组成,其中每条逻辑行是一条物理行(巧合)。我没有看到一条逻辑线如何跨越边界(这基本上只是结尾的一个奇特的词,限制,这是换行符),我看不出一个语句如何跨越这些边界并跨越到下一个声明,或者我真的很困惑,一切都搞砸了,但如果有人可以请解释。

      感谢您提前抽出时间。

2 个答案:

答案 0 :(得分:4)

Pythons语法

幸运的是,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语句包括 elseNEWLINE以及其中的所有内容都是一个语句(复合语句)。因为它可能包含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语句(并且它不仅仅是由whileif“控制”的块,...)。

parsersymboltoken

相同的parser

可视化的方法是使用内置的tokensymbolimport 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() 语句。这就是语句如何跨越逻辑行边界。