[译]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)。例:<letter>, <digit>
  • Rules(规则): 定义terminalsNonterminals的联系。 如:<letter> ::= "a"

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

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

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

BNF规则及其组成部分

BNF规则的格式通常如下:

<symbol> ::= expression

其中

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

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

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

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

一般示例:全名的语法

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

<full_name> ::= <first_name> " " (<middle_name> " ")? <family_name>

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

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

我们还需要定义<first_name>, <middle_name>, <family_name>的规则。

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

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

<uppercase_letter> ::= [A-Z]
<lowercase_letter> ::= [a-z]

接着,我们可以定义<first_name>, <middle_name>, <family_name>的规则:

<first_name>       ::= <uppercase_letter> <lowercase_letter>*

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

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

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

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

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

可以写出相应的BNF规则:

<identifier> ::= <char> (<char> | <digit>)*

其中<char><digit>进一步定义:

<char>       ::= [A-Z] | [a-z] | "_"
<digit>      ::= [0-9]

我们可以在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"

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

pass

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

return_stmt ::= "return" [expression_list]

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

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

def func():return

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

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

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

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

def func():return "Hello!", "Pythonista!"

赋值表达式

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

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

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

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

identifier := expression

例如

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

条件语句

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

if_stmt ::=  "if" assignment_expression ":" suite("elif" assignment_expression ":" suite)*["else" ":" suite]

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

if assignment_expression:suite

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

if assignment_expression:suite
elif assignment_expression:suite

最后是可选的else:

if assignment_expression:suite
elif assignment_expression:suite
else:suite

循环语句

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

  • for循环
  • while循环

for 循环的 BNF 语法如下:

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

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

for target_list in starred_list:suite
else:suite

例如:

high = 5for number in range(high):if number > 5:breakprint(number)
else:print("range covered")

while 循环的 BNF 语法如下:

while_stmt ::=  "while" assignment_expression ":" suite["else" ":" suite]

可以写出while语句:

while assignment_expression:suite
else:suite

读取 Python BNF 的最佳实践

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

  1. 熟悉BNF表示法。可以编写BNF规则并在BNF Playground网站中测试。
  2. 了解Python的BNF变体。
  3. 分解规则。将规则分成多个部分来阅读。
  4. 识别非终止符。非终止符可能需要进一步阅读。
  5. 了解终止符。 查找表示语言中特定元素的终止符,例如关键字、运算符、文本或标识符。这些符号被引号括起来。
  6. 结合实例:研究与您试图理解的 BNF 规则相对应的实际示例。分析 BNF 规则如何应用于这些示例。将规则与实际的 Python 语法进行对比。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/512044.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pytest框架中的测试用例执行方式!

前言 本文将针对pytest的核心特性之一——测试用例的执行方式展开深入探讨&#xff0c;并通过详尽的实战示例展示如何在不同环境下灵活操控测试运行&#xff0c;同时全面解析pytest中常见的且极具实用价值的命令行选项。 一、从基础到进阶&#xff1a;pytest在命令行下的测试用…

解决岗位招聘、绩效管理及员工培训问题,这样做

许多企业在发展过程中&#xff0c;会遇到一系列的管理问题&#xff0c;比如优秀人才匮乏、人才流失严重、人才素质整体水平较低等&#xff0c;这些管理问题严重影响了企业的进一步发展。如何解决这些问题成为企业管理者关注的重点。我们一起来看看华恒智信提供的针对性解决思路…

【力扣精选算法100道】——判定是否互为字符重排(哈希专题)

目录 &#x1f6a9;了解题意 &#x1f6a9;算法原理 第一种&#xff1a;排序 第二种方法&#xff1a;哈希 &#x1f6a9;实现代码 面试题 01.02. 判定是否互为字符重排 - 力扣&#xff08;LeetCode&#xff09; &#x1f6a9;了解题意 我们输入俩个字符串&#xff0c;当俩…

如何在服务器上建立国外私有云存储

随着数字化时代的到来&#xff0c;数据备份和存储成为了我们生活与工作中不可或缺的一部分。私有云存储&#xff0c;以其灵活性、安全性和便捷性&#xff0c;受到了越来越多用户的青睐。特别是对于需要在国外服务器上建立私有云存储的用户来说&#xff0c;这一需求更加迫切。下…

超详细Prometheus入门教程!(内含141页可复制官方文档下载方式)

141页的Prometheus官方中文文档&#xff0c;由于内容过多&#xff0c;在此只以截图展示部分内容&#xff0c;详细完整版的文档请见文末。 这份Prometheus官方中文文档既适合小白入门也适合有一定基础的同学进阶提升。这份文档共分为7大部分&#xff0c;从最基础的Prometheus介绍…

倾斜三维模型OSGB路径漫游——DasViewer

背景 有时候我们需要查看倾斜三维模型效果的效果&#xff0c;虽然也有很多软件可以用&#xff0c;比如CC、超图等等&#xff0c;但是这些软件都比较大&#xff0c;安装也比较麻烦&#xff0c;DasViewer这个软件就比较轻量&#xff0c;安装也简单&#xff0c;功能强大&#xff…

uniapp实现进度条组件

首先&#xff0c;在uniapp项目中创建一个自定义组件&#xff0c;可以命名为Progress.vue。在Progress.vue中&#xff0c;编写如下代码&#xff1a; <template><view class"progress"><view class"progress-bar" :style"{width: progr…

拿到年终奖马上离职,厚道吗?

拿到年终奖马上离职&#xff0c;厚道吗&#xff1f; 大家好&#xff0c;我是銘&#xff0c;全栈开发程序员。 今天在知乎上看到一个问题&#xff1a;拿到年终奖后马上辞职&#xff0c;厚道吗&#xff1f; image-20240229232132786 我的答案是&#xff1a;厚道&#xff0c;非常厚…

7.1.2 Selenium的用法1

目录 1. 初始化浏览器对象和访问页面 2. 查找节点及节点交互 2.1 查找单个节点 &#xff08;1&#xff09;获取方法1——特定方法 &#xff08;2&#xff09;通用方法 2.2 查找多个节点 2.3 节点交互 3. 动作链 4. 执行 JavaScript 之下拉进度条 5. 获取节点信息 5.…

视觉slam十四讲学习笔记(七)视觉里程计 2

介绍直接法的原理&#xff0c;并利用 g2o 实现直接法中的一些核心算法。 前言 1. 理解光流法跟踪特征点的原理。 2. 理解直接法是如何估计相机位姿的。 3. 使用 g2o 进行直接法的计算。 哔哩哔哩课程连接&#xff1a;视觉SLAM十四讲ch7_2_哔哩哔哩_bilibili 一、直接法…

小程序分销系统怎么开发_开启您的智能营销新时代

小程序分销系统&#xff1a;开启您的智能营销新时代 随着移动互联网的迅猛发展&#xff0c;微信小程序以其轻便、快捷的特性赢得了广大用户的喜爱。而在激烈的市场竞争中&#xff0c;如何借助小程序这一工具&#xff0c;实现产品的快速传播和销售&#xff0c;成为了众多商家关…

面试问答总结之Java进阶

文章目录 &#x1f412;个人主页&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;注解Annotaion &#xff08;java标注&#xff09;&#x1f415;内置注解&#x1f415;元注解 &#x1f380;对象克隆&#x1f415;如何实现克隆&#x1f415;如何实现深克…