Python 语言参考手册

本参考手册介绍了 Python 句法与“核心语义”。

2 词法分析

Python 程序由 解析器 读取,输入解析器的是 词法分析器 生成的 形符 流。本章介绍词法分析器怎样把文件拆成形符。

Python 将读取的程序文本转为 Unicode 代码点;编码声明用于指定源文件的编码,默认为 UTF-8。源文件不能解码时,触发 SyntaxError

2.1 行结构

Python 程序可以拆分为多个 逻辑行。

2.1.1 逻辑行

NEWLINE 形符表示结束逻辑行。语句不能超出逻辑行的边界,除非句法支持 NEWLINE (例如,复合语句中的多行子语句)。根据显式或隐式 行拼接 规则,一个或多个 物理行 可组成逻辑行。

2.1.2 物理行

物理行是一序列字符,由行尾序列终止。源文件和字符串可使用任意标准平台行终止序列 - Unix ASCII 字符 LF(换行)、 Windows ASCII 字符序列 CR LF(回车换行)、或老式 Macintosh ASCII 字符 CR(回车)。不管在哪个平台,这些形式均可等价使用。输入结束也可以用作最终物理行的隐式终止符。

嵌入 Python 时,传入 Python API 的源码字符串应使用 C 标准惯例换行符(\n,代表 ASCII 字符 LF,行终止符)。

2.1.3 注释

注释以井号(#)开头,在物理行末尾截止。注意,井号不是字符串字面值。除非应用隐式行拼接规则,否则,注释代表逻辑行结束。句法不解析注释。

2.1.4 编码声明

Python 脚本第一或第二行的注释匹配正则表达式 coding[=:]\s*([-\w.]+) 时,该注释会被当作编码声明;这个表达式的第一组指定了源码文件的编码。编码声明必须独占一行,在第二行时,则第一行必须也是注释。编码表达式的形式如下:

# -*- coding: <encoding-name> -*-

此外,还支持如下形式:

# vim:fileencoding=<encoding-name>

没有编码声明时,默认编码为 UTF-8。此外,如果文件的首字节为 UTF-8 字节顺序标志(b'\xef\xbb\xbf'),文件编码也声明为 UTF-8。

2.1.5 显式拼接行

两个及两个以上的物理行可用反斜杠(\)拼接为一个逻辑行,规则如下:以不在字符串或注释内的反斜杠结尾时,物理行将与下一行拼接成一个逻辑行,并删除反斜杠及其后的换行符。例如:

if 1900 < year < 2100 and 1 <= month <= 12 \
   and 1 <= day <= 31 and 0 <= hour < 24 \
   and 0 <= minute < 60 and 0 <= second < 60:   # Looks like a valid date
        return 1

以反斜杠结尾的行,不能加注释;反斜杠也不能拼接注释。除字符串字面值外,反斜杠不能拼接形符(如,除字符串字面值外,不能用反斜杠把形符切分至两个物理行)。反斜杠只能在代码的字符串字面值里,在其他任何位置都是非法的。

2.1.6 隐式拼接行

圆括号、方括号、花括号内的表达式可以分成多个物理行,不必使用反斜杠。例如:

month_names = ['Januari', 'Februari', 'Maart',      # These are the
               'April',   'Mei',      'Juni',       # Dutch names
               'Juli',    'Augustus', 'September',  # for the months
               'Oktober', 'November', 'December']   # of the year

隐式行拼接可含注释;后续行的缩进并不重要;还支持空的后续行。隐式拼接行之间没有 NEWLINE 形符。三引号字符串支持隐式拼接行(见下文),但不支持注释。

2.1.7 空白行

只包含空格符、制表符、换页符、注释的逻辑行会被忽略(即不生成 NEWLINE 形符)。

2.1.8 缩进

逻辑行开头的空白符(空格符和制表符)用于计算该行的缩进层级,决定语句组块。

2.1.9 形符间的空白字符

除非在逻辑行开头或字符串内,空格符、制表符、换页符等空白符都可以分隔形符。要把两个相连形符解读为不同形符,需要用空白符分隔(例如,ab 是一个形符,a b 则是两个形符)。

2.2 其他形符

除 NEWLINE、INDENT、DEDENT 外,还有 标识符、关键字、字面值、运算符 、分隔符 等形符。 空白符(前述的行终止符除外)不是形符,可用于分隔形符。存在二义性时,将从左至右,读取尽量长的字符串组成合法形符。

2.3 标识符和关键字

以下标识符为保留字,或称 关键字,不可用于普通标识符。关键字的拼写必须与这里列出的完全一致:

False      await      else       import     pass
None       break      except     in         raise
True       class      finally    is         return
and        continue   for        lambda     try
as         def        from       nonlocal   while
assert     del        global     not        with
async      elif       if         or         yield

(王)关键字解释:
1. async\await 的使用
正常的函数在执行时是不会中断的,所以你要写一个能够中断的函数,就需要添加async关键。

async 用来声明一个函数为异步函数,异步函数的特点是能在函数执行过程中挂起,去执行其他异步函数,等到挂起条件(假设挂起条件是sleep(5))消失后,也就是5秒到了再回来执行。

await 用来用来声明程序挂起,比如异步程序执行到某一步时需要等待的时间很长,就将此挂起,去执行其他的异步程序。await 后面只能跟异步程序或有 __await__ 属性的对象,因为异步程序与一般程序不同。假设有两个异步函数async a,async b,a中的某一步有await,当程序碰到关键字await b()后,异步程序挂起后去执行另一个异步b程序,就是从函数内部跳出去执行其他函数,当挂起条件消失后,不管b是否执行完,要马上从b程序中跳出来,回到原程序执行原来的操作。如果await后面跟的b函数不是异步函数,那么操作就只能等b执行完再返回,无法在b执行的过程中返回。如果要在b执行完才返回,也就不需要用await关键字了,直接调用b函数就行。所以这就需要await后面跟的是异步函数了。在一个异步函数中,可以不止一次挂起,也就是可以用多个await。

2. pass
pass 是空语句,是为了保持程序结构的完整性。

pass 不做任何事情,一般用做占位语句。

3. except
except 用来捕获所有异常。

4. raise
raise 用来手动设置异常。

5. nonlocal
nonlocal 声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量。

6. del
由于python都是引用,而python有GC机制,所以,del 语句作用在变量上,而不是数据对象上。

if __name__=='__main__':  
    a=1       # 对象 1 被 变量a引用,对象1的引用计数器为1  
    b=a       # 对象1 被变量b引用,对象1的引用计数器加1  
    c=a       #1对象1 被变量c引用,对象1的引用计数器加1  
    del a     #删除变量a,解除a对1的引用  
    del b     #删除变量b,解除b对1的引用  
    print(c)  #最终变量c仍然引用1  

del 删除的是变量,而不是数据。

if __name__=='__main__':  
    li=[1,2,3,4,5]  #列表本身不包含数据1,2,3,4,5,而是包含变量:li[0] li[1] li[2] li[3] li[4]   
    first=li[0]     #拷贝列表,也不会有数据对象的复制,而是创建新的变量引用  
    del li[0]  
    print(li)      #输出[2, 3, 4, 5]  
    print(first)   #输出 1  

7. yield
首先,如果你还没有对yield有个初步的认识,那么你先把yield看做“return”,这个是直观的,它首先是个return,普通的return是什么意思,就是在程序中返回某个值,返回之后程序就不再往下运行了。 看做return之后再把它看做是生成器(generator)的一部分(带yield的函数才是真正的迭代器)。 好了,如果你对这些不明白的话,那先把yield看做return,然后直接看下面的程序,你就会明白yield的全部意思了:

def foo():
    print("starting...")
    while True:
        res = yield 4
        print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(next(g))

就这么简单的几行代码就让你明白什么是yield,代码的输出这个:

starting...
4
********************
res: None
4

我直接解释代码运行顺序,相当于代码单步调试:
1.程序开始执行以后,因为foo函数中有yield关键字,所以foo函数并不会真的执行,而是先得到一个生成器g(相当于一个对象)
2.直到调用next方法,foo函数正式开始执行,先执行foo函数中的print方法,然后进入while循环
3.程序遇到yield关键字,然后把yield想想成return,return了一个4之后,程序停止,并没有执行赋值给res操作,此时next(g)语句执行完成,所以输出的前两行(第一个是while上面的print的结果,第二个是return出的结果)是执行print(next(g))的结果,
4.程序执行print("*"20),输出20个
5.又开始执行下面的print(next(g)),这个时候和上面那个差不多,不过不同的是,这个时候是从刚才那个next程序停止的地方开始执行的,也就是要执行res的赋值操作,这时候要注意,这个时候赋值操作的右边是没有值的(因为刚才那个是return出去了,并没有给赋值操作的左边传参数),所以这个时候res赋值是None,所以接着下面的输出就是res:None,
6.程序会继续在while里执行,又一次碰到yield,这个时候同样return 出4,然后程序停止,print函数输出的4就是这次return出的4.

到这里你可能就明白yield和return的关系和区别了,带yield的函数是一个生成器,而不是一个函数了,这个生成器有一个函数就是next函数,next就相当于“下一步”生成哪个数,这一次的next开始的地方是接着上一次的next停止的地方执行的,所以调用next的时候,生成器并不会从foo函数的开始执行,只是接着上一步停止的地方开始,然后遇到yield后,return出要生成的数,此步就结束。


def foo():
    print("starting...")
    while True:
        res = yield 4
        print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(g.send(7))

再看一个这个生成器的send函数的例子,这个例子就把上面那个例子的最后一行换掉了,输出结果:

starting...
4
********************
res: 7
4

先大致说一下send函数的概念:此时你应该注意到上面那个的紫色的字,还有上面那个res的值为什么是None,这个变成了7,到底为什么,这是因为,send是发送一个参数给res的,因为上面讲到,return的时候,并没有把4赋值给res,下次执行的时候只好继续执行赋值操作,只好赋值为None了,而如果用send的话,开始执行的时候,先接着上一次(return 4之后)执行,先把7赋值给了res,然后执行next的作用,遇见下一回的yield,return出结果后结束。

5.程序执行g.send(7),程序会从yield关键字那一行继续向下运行,send会把7这个值赋值给res变量

6.由于send方法中包含next()方法,所以程序会继续向下运行执行print方法,然后再次进入while循环

7.程序执行再次遇到yield关键字,yield会返回后面的值后,程序再次暂停,直到再次调用next方法或send方法。

这就结束了,说一下,为什么用这个生成器,是因为如果用List的话,会占用更大的空间,比如说取 0,1,2,3,4,5,6…1000

你可能会这样:

for n in range(1000):
    a=n

这个时候range(1000)就默认生成一个含有1000个数的list了,所以很占内存。
这个时候你可以用刚才的yield组合成生成器进行实现,也可以用xrange(1000)这个生成器实现 yield 组合:

def foo(num):
    print("starting...")
    while num<10:
        num=num+1
        yield num
for n in foo(0):
    print(n)

输出:

starting...
1
2
3
4
5
6
7
8
9
10

xrange(1000):

for n in xrange(1000):
    a=n

其中要注意的是python3时已经没有xrange()了,在python3中,range()就是xrange()了,你可以在python3中查看range()的类型,它已经是个<class ‘range’>了,而不是一个list了,毕竟这个是需要优化的。

2.3.2 软关键字

某些标识符仅在特定上下文中被保留。 它们被称为 软关键字。 match, case 和 _ 等标识符在模式匹配语句相关的上下文中具有相当于关键字的语义,但这种区分是在解析器层级完成,而不是在形符化的时候。

作为软关键字,它们能够与模式匹配一起使用,同时仍然保持与使用 match, case 和 _ 作为标识符名称的现有代码的兼容性。

2.3.3 保留的标识符类

_*

_

__*__

__*

2.4 字面值

字面值是内置类型常量值的表示法。

2.4.1 字符串与字节串字面值

字符串字面值的词法定义如下:

stringliteral   ::=  [stringprefix](shortstring | longstring)
stringprefix    ::=  "r" | "u" | "R" | "U" | "f" | "F"
                     | "fr" | "Fr" | "fR" | "FR" | "rf" | "rF" | "Rf" | "RF"
shortstring     ::=  "'" shortstringitem* "'" | '"' shortstringitem* '"'
longstring      ::=  "'''" longstringitem* "'''" | '"""' longstringitem* '"""'
shortstringitem ::=  shortstringchar | stringescapeseq
longstringitem  ::=  longstringchar | stringescapeseq
shortstringchar ::=  <any source character except "\" or newline or the quote>
longstringchar  ::=  <any source character except "\">
stringescapeseq ::=  "\" <any source character>
bytesliteral   ::=  bytesprefix(shortbytes | longbytes)
bytesprefix    ::=  "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"
shortbytes     ::=  "'" shortbytesitem* "'" | '"' shortbytesitem* '"'
longbytes      ::=  "'''" longbytesitem* "'''" | '"""' longbytesitem* '"""'
shortbytesitem ::=  shortbyteschar | bytesescapeseq
longbytesitem  ::=  longbyteschar | bytesescapeseq
shortbyteschar ::=  <any ASCII character except "\" or newline or the quote>
longbyteschar  ::=  <any ASCII character except "\">
bytesescapeseq ::=  "\" <any ASCII character>

通俗地说:两种字面值都可以用单引号(’)或双引号(") 标注。也可以用三个单引号或双引号标注(俗称 三引号字符串)。反斜杠(\)用于转义特殊字符,例如,换行符、反斜杠本身、引号等。

字节串字面值要加前缀 ‘b’ 或 ‘B’;生成的是类型 bytes 的实例,不是类型 str 的实例;字节串只能包含 ASCII 字符;字节串数值大于等于 128 时,必须用转义表示。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python is an extensible, interpreted, object-oriented programming language. It supports a wide range of applica- tions, from simple text processing scripts to interactive Web browsers. Python 是一种可扩展的, 即译式, 面向对象规格的编程语言. 它能应用在极广泛的地方, 从简单的文字处理 工作到交互式的网页浏览器. While the Python Reference Manual describes the exact syntax and semantics of the language, it does not describe the standard library that is distributed with the language, and which greatly enhances its immediate usability. This library contains built-in modules (written in C) that provide access to system functionality such as file I/O that would otherwise be inaccessible to Python programmers, as well as modules written in Python that provide standardized solutions for many problems that occur in everyday programming. Some of these modules are explicitly designed to encourage and enhance the portability of Python programs. Python 语言参考手册 中精确地描述了Python 语言的句法及语义. 然而语言参考手册中没有提到Python 所 附带功能强大的标准库. 这个函式库大大地增强了Python 的实用性. 其中包括C 写的内建模组, 提供介面 让程式进行操作系统层次的工作, 例如档案的输出输入; 同时也有以Python 语言本身编写的模组, 为实际 编程时常遇的问题提供标准解决方案. 这类模组有的经过特别设计以便Python 程式在跨平台的情况下运 行无误. This library reference manual documents Python’s standard library, as well as many optional library modules (which may or may not be available, depending on whether the underlying platform supports them and on the configuration choices made at compile time). It also documents the standard types of the language and its built-in functions and exceptions, many of which are not or incompletely documented in the Reference Manual. 本参考手册罗列并说明了Python 标准库的各种功能, 以及许多非核心的模组(按不同的操作系统和编译时 的设置而定, 不是每台机上的Python 都能用这些模组.) 本手册同时记载了Python 语言所有的标准数据类 型, 内建函数, 异常类, 这些在参考手册中被忽略了或只是扼要的提过一下. This manual assumes basic knowledge about the Python language. For an informal introduction to Python, see the Python Tutorial; the Python Reference Manual remains the highest authority on syntactic and semantic questions. Finally, the manual entitled Extending and Embedding the Python Interpreter describes how to add new extensions to Python and how to embed it in other applications. 本手册的读者要对Python 有基本的认识. 初学者应该从Python 指南 开始. 至于Python 语言参考手册 则是该语言的语法和语义问题上的权威阐释. 最后 扩展或嵌入 Python 解释器 一文解说了如何在Python 中加入新的扩展模组; 以及怎样把Python 解释器嵌入到其他的应用程式中.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淘淘图兔兔呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值