• [译]BNF 表示法:深入了解 Python 的语法


    [译]BNF 表示法:深入了解 Python 的语法

    原文:《BNF Notation: Dive Deeper Into Python’s Grammar》
    https://realpython.com/python-bnf-notation/

    在阅读Python文档的时候,你可能已经遇到过BNF(Backus–Naur form)表示法:
    文档中的BNF

    下面我们将了解BNF表示法,以及如何使用它来理解Python的语法。

    理解BNF表示法

    BNF是上下文无关语法的元语法符号计算机科学家经常使用这种符号来描述编程语言的语法,因为它允许他们编写语言语法的详细描述。

    BNF 符号由三个核心部分组成:

    • Terminals(终止符):必须与输入中的特定项完全匹配的字符串。例:"def", "return, ":"
    • Nonterminals(非终止符):会被替换为具体值的符号。也可称为句法变量(syntactic variables)。例:,
    • Rules(规则): 定义terminalsNonterminals的联系。 如: ::= "a"

    通过组合终止符非终止符,可以创建出BNF 规则

    通过定义一组规则,可以构建出一个语言的语法(grammar)。

    BNF具有一些变体,如EBNF和ABNF。

    BNF规则及其组成部分

    BNF规则的格式通常如下:

     ::= expression
    
    • 1

    其中

    • :符号是一个非终止符变量,通常用<>括起来。
    • ::=: 表示左边的非终止符会被右边的表达式替换。
    • expression:表达式由一系列终止符、非终止符和其它符号组成。

    在构建BNF规则时,你可以定义一些符号表示不同含义,例如:

    符号含义
    ""将终止符括起来
    <>表示非终止符
    ()表示一组有效选项
    +指定上一个元素中的一个或多个
    *…零个或多个
    ?…零个或一个
    |选择其中一个
    [x-z]字母或数字区间

    下面我们尝试自定义一些BNF规则。

    一般示例:全名的语法

    现在我们尝试定义一个人的全名的语法,一个人的全名包含3部分:
    first name, middle name, family name
    每个部分之间应该用空格分隔,middle name是可选的。

     ::=  " " ( " ")? 
    
    • 1

    规则的左侧部分是一个非终止符变量,用于标识人员的全名。::= 符号表示 将替换为规则的右侧部分。

    规则的右侧部分有几个组成部分。首先是first name,使用非终止符定义。
    接下来是一个空格。为了定义空格,要使用一个终止符,即" "
    接下来,我们有一个可选的middle_name,使用( " ")?定义。
    最后,我们有一个家庭名,使用定义。

    我们还需要定义, , 的规则。

    • 只接受字母
    • 首字母大写,其余小写

    我们又引入了大写字母和小写字母两个非终止符,需要进一步定义:

     ::= [A-Z]
     ::= [a-z]
    
    • 1
    • 2

    接着,我们可以定义, , 的规则:

           ::=  *
    
    • 1

    您可以按照相同的模式来构建 规则。

    我们构建完了一个full name的BNF规则。
    下面我们在BNF Playground网站中测试这个规则。
    在这里插入图片描述

    与编程相关的示例:标识符

    在学习编程语言时,我们很早就会接触到标识符(Identifiers)的概念。
    标识符是用来标识变量、函数、类等的名称。
    在Python中,标识符的命名规则如下:

    • 第一个字符是字母、下划线。
    • 其余字符可以是字母、下划线或数字。

    可以写出相应的BNF规则:

     ::=  ( | )*
    
    • 1

    其中进一步定义:

           ::= [A-Z] | [a-z] | "_"
          ::= [0-9]
    
    • 1
    • 2

    我们可以在BNF Playground网站中测试这个规则。

    Python的BNF变体

    Python 使用 BNF 表示法的自定义变体来定义语言的语法。

    Python 的 BNF 变体使用以下样式:

    符号含义
    name规则或非终止符的名称
    ::=意味着
    ``
    *零个或多个
    +一个或多个
    []零个或一个,即可选项
    ()分组
    |文本字符串
    space仅对分隔令牌有意义

    这些符号定义了 Python 的 BNF 变体。与常规 BNF 规则的一个显着区别是Python不使用尖括号( <> )来括起非终端符号。它仅使用非终端标识符或名称。这使得规则更简洁易读。
    另外,[]的含义不再是字符集,而是可选项。要定义类似于BNF的[a-z],需要使用"a"..."z"

    在Python文档经常会遇到BNF代码片段,有必要学习如何阅读它们。

    从 Python 的文档中读取 BNF 规则:示例

    pass 和 return 语句

    这是Python的pass语句

    pass_stmt ::=  "pass"
    
    • 1

    这里,pass_stmt是一个规则的名称,使用::=指示规则扩展为"pass""pass"是一个终止符,意味着语句本身由单词pass组成。
    因此,pass语句只是一个单词

    pass
    
    • 1

    另一个常见的语句是return语句:

    return_stmt ::= "return" [expression_list]
    
    • 1

    return语句由"return"[expression_list]组成。expression_list是一个非终止符,[]表示它是可选的。

    因此你可以这样使用return语句

    def func():
        return
    
    • 1
    • 2

    如果你进入expression_list的定义,你会看到

    expression_list ::= expression ("," expression)* [","]
    
    • 1

    又出现了一个非终止符expression,你可以继续查看expression的定义。

    通过该定义,你可以了解到return语句可以返回一个或多个(用,隔开)表达式。

    def func():
        return "Hello!", "Pythonista!"
    
    • 1
    • 2

    赋值表达式

    Python 3.8 引入了赋值表达式:=(称为walrus运算符/象牙运算符)。作用是给变量赋值并返回表达式的值。

    assignment_expression ::=  [identifier ":="] expression
    
    • 1

    规则的右侧先是一个可选的组件,由一个标识符和一个终止符:=组成。然后是一个表达式。

    我们可以在python中使用赋值表达式:

    identifier := expression
    
    • 1

    例如

    >>> (length := len([1, 2, 3]))
    3
    >>> length
    3
    
    • 1
    • 2
    • 3
    • 4

    条件语句

    我们现在进阶到复合语句了。
    if语句的BNF规则如下:

    if_stmt ::=  "if" assignment_expression ":" suite
                 ("elif" assignment_expression ":" suite)*
                 ["else" ":" suite]
    
    • 1
    • 2
    • 3

    首先是终止符if,然后是assignment_expression(上一节已经讨论过)。然后是终止符:, 非终止符suite
    安装刚刚读的定义,我们可以写出下面的if语句:

    if assignment_expression:
        suite
    
    • 1
    • 2

    继续看定义,我们有了可选的elif:

    if assignment_expression:
        suite
    elif assignment_expression:
        suite
    
    • 1
    • 2
    • 3
    • 4

    最后是可选的else:

    if assignment_expression:
        suite
    elif assignment_expression:
        suite
    else:
        suite
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    循环语句

    循环是 Python 中另一个常用的复合语句。Python中有两种循环:

    • for循环
    • while循环

    for 循环的 BNF 语法如下:

    for_stmt ::=  "for" target_list "in" starred_list ":" suite
                  ["else" ":" suite]
    
    • 1
    • 2

    于是我们可以写出for语句:

    for target_list in starred_list:
        suite
    else:
        suite
    
    • 1
    • 2
    • 3
    • 4

    例如:

    high = 5
    
    for number in range(high):
        if number > 5:
            break
        print(number)
    else:
        print("range covered")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    while 循环的 BNF 语法如下:

    while_stmt ::=  "while" assignment_expression ":" suite
                    ["else" ":" suite]
    
    • 1
    • 2

    可以写出while语句:

    while assignment_expression:
        suite
    else:
        suite
    
    • 1
    • 2
    • 3
    • 4

    读取 Python BNF 的最佳实践

    当您阅读文档中的 Python 的 BNF 规则时,您可以遵循一些最佳实践来提高您的理解。以下是一些建议:

    1. 熟悉BNF表示法。可以编写BNF规则并在BNF Playground网站中测试。
    2. 了解Python的BNF变体。
    3. 分解规则。将规则分成多个部分来阅读。
    4. 识别非终止符。非终止符可能需要进一步阅读。
    5. 了解终止符。 查找表示语言中特定元素的终止符,例如关键字、运算符、文本或标识符。这些符号被引号括起来。
    6. 结合实例:研究与您试图理解的 BNF 规则相对应的实际示例。分析 BNF 规则如何应用于这些示例。将规则与实际的 Python 语法进行对比。
  • 相关阅读:
    python-----发邮件
    为什么Dapr是比SpringCloud和Istio更优雅的微服务框架?
    类和对象(6):const成员,&/const &重载
    怎么让英文大预言模型支持中文?(一)构建自己的tokenization
    双-(二苯胺基-苯基)-苯并[c]硫代咪唑聚集诱导发光微球/四苯基乙烯聚集诱导发光AIE微球
    创建不了企业百度百科怎么办,申请百度百科的攻略
    notepad++下载地址
    JSP概述
    DPDK之PMD原理
    Python 多线程与多进程
  • 原文地址:https://blog.csdn.net/qq_41068877/article/details/136375959