首页 / 资讯中心 / 文章详情

Python:词法分析(行结构与显式、隐式行拼接)

Python:词法分析(行结构与显式、隐式行拼接) ★ FEATURED ARTICLE
相关阅读Pythonhttps://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.54821、逻辑结构一个Python程序由许多逻辑行组成字面意义上的一行指的是末尾有换行符(\n)但在不同的情况下行末尾的换行符(\n)可能有不同的意义。2、逻辑行逻辑行的结尾的换行符(\n)被解析为NEWLINE标记。一般来说一条语句不能跨越逻辑行而存在除非是复合语句如if复合语句可以由多个逻辑行组成但一个逻辑行可能有多条语句如使用分号分隔语句。print(1) # 逻辑行 if (a): # 逻辑行 print(1) # 逻辑行 else: # 逻辑行 print(2) # 逻辑行 print(3);print(4) # 逻辑行如果是交互式Python解释对于简单语句来说逻辑行末尾的换行符表示将文本提供给解释器进行执行对于复合语句来说最后一个逻辑行末尾的换行符表示将文本提供给解释器进行执行。3、物理行根据显式或隐式行拼接规则若干个物理行可以组成逻辑行物理行的结尾的换行符(\n)可以被解析为NEWLINE标记如果这个物理行是一个逻辑行中的最后一个物理行或者NL标记如果这个物理行不是一个逻辑行中的最后一个物理行或者在进行显式行拼接时与反斜杠(\)一起被删除。total (1 2 3 # 物理行 # 逻辑行 4 5 6) # 物理行如果是交互式Python解释对于简单语句来说物理行末尾的换行符表示将文本提供给解释器进行编译如果这个物理行是一个逻辑行中的最后一个物理行还会执行。4、注释注释是一种特殊的逻辑行对于单行是完全的注释它末尾的换行符(\n)会被解析为NL标记。而一个位于逻辑行末尾的注释它末尾的换行符(\n)则会被解释为NEWLINE标记。但无论是哪种解释注释代表着从#到换行符(\n)之间的内容不包括换行符(\n)会被解析为一个整体即注释标记而对程序无任何影响。5、显式行拼接两个及两个以上的物理行可用反斜杠(\)显式拼接为一个逻辑行规则如下除了注释中的反斜杠(\)加换行符(\n)结尾外因为这时的反斜杠(\)已经被当做了注释这也代表着注释无论如何不会影响到下一行物理行将与从上到下一次拼接直到一个逻辑行并删除末尾的反斜杠(\)及其后的换行符(\n)当使用反斜杠(\)时末尾不允许有注释因为这样反斜杠(\)后面就没有换行符(\n)也就无法行拼接了。需要注意的是显式行拼接无法拼接除字符串字面量外的标记而后面谈到的的隐式拼接无法拼接任何标记标记即一个解析的整体例如函数print是一个标记字符串aaa是一个标记而1 1包含三个标记因为其中不属于行首的空格、制表符等空白符不会被解析为标记而行首的空格、制表符被解析为缩进标记。下面来看几个例子if 1900 year 2100 and 1 month 12 \ and 1 day 31 and 0 hour 24 \ and 0 minute 60 and 0 second 60: # 这里的注释是允许的而上两行末尾再加注释是不允许的因为这样\后面就没有换行符了 return 1 #正确的显式行拼接因为并没有分割任何标记 a 1 \ 2 #错误的显式行拼接因为分割了标记语法分析时会产生错误解析 pr\ int(hello world!) #正确的显式行拼接虽然字符串aaa是一个标记但这是唯一的例外 a aa\ a如何更加直观的验证上面的这些分析有什么方法吗当然有tokenize包可以帮助我们解析一串代码下面给出一段测试程序。import tokenize from io import BytesIO code The code you are testing # 将代码字符串转换为字节流 code_bytes code.encode(utf-8) code_stream BytesIO(code_bytes) # 使用tokenize.tokenize生成tokens tokens tokenize.tokenize(code_stream.readline) # 遍历tokens并打印信息 for token in tokens: print(token)根据自己的需要你可以将任何一段程序粘贴进上面的相应位置进行验证使用三引号()的原因是它能保留跨行字符串而不使用反斜杠(\)。这很重要因为如果使用双引号()则无法测试下一节没有反斜杠(\)的隐式行连接因为这代表着没有反斜杠(\)的字符串被分成了两行但上面说过隐式行连接无法拼接任何标记所以甚至连测试程序都无法通过语法分析下面我们看一个测试结果。import tokenize from io import BytesIO code a 1 \ 2 # 将代码字符串转换为字节流 code_bytes code.encode(utf-8) code_stream BytesIO(code_bytes) # 使用tokenize.tokenize生成tokens tokens tokenize.tokenize(code_stream.readline) # 遍历tokens并打印信息 for token in tokens: print(token) TokenInfo(type62 (ENCODING), stringutf-8, start(0, 0), end(0, 0), line) TokenInfo(type1 (NAME), stringa, start(1, 0), end(1, 1), linea 1 2) TokenInfo(type54 (OP), string, start(1, 2), end(1, 3), linea 1 2) TokenInfo(type2 (NUMBER), string1, start(1, 4), end(1, 5), linea 1 2) TokenInfo(type54 (OP), string, start(1, 6), end(1, 7), linea 1 2) TokenInfo(type2 (NUMBER), string2, start(1, 8), end(1, 9), linea 1 2) TokenInfo(type4 (NEWLINE), string, start(1, 9), end(1, 10), line) TokenInfo(type0 (ENDMARKER), string, start(2, 0), end(2, 0), line)从上面的解析结果可以看出确实两物理行被拼接成了一逻辑行而末尾的反斜杠(\)与换行符(\n)消失所以没有解析成标记。6、隐式行拼接隐式拼接的圆括号、方括号、花括号内的表达式可以分成多个物理行不必使用反斜杠。例如month_names [Januari, Februari, Maart, # 这里 April, Mei, Juni, # 可以 Juli, Augustus, September, # 加注释 Oktober, November, December] # 这并不会有影响 #正确的隐式行拼接没有分隔标记 a (1 2) #正确的隐式行拼接没有分隔标记 a [1, 2] #正确的隐式行拼接没有分隔标记 a {1, 2} #错误的隐式行拼接分隔了标记 prin t(hello world!)下面我们看一个测试结果import tokenize from io import BytesIO code a (1 2) # 将代码字符串转换为字节流 code_bytes code.encode(utf-8) code_stream BytesIO(code_bytes) # 使用tokenize.tokenize生成tokens tokens tokenize.tokenize(code_stream.readline) # 遍历tokens并打印信息 for token in tokens: print(token) TokenInfo(type62 (ENCODING), stringutf-8, start(0, 0), end(0, 0), line) TokenInfo(type1 (NAME), stringa, start(1, 0), end(1, 1), linea (1 \n) TokenInfo(type54 (OP), string, start(1, 2), end(1, 3), linea (1 \n) TokenInfo(type54 (OP), string(, start(1, 4), end(1, 5), linea (1 \n) TokenInfo(type2 (NUMBER), string1, start(1, 5), end(1, 6), linea (1 \n) TokenInfo(type54 (OP), string, start(1, 7), end(1, 8), linea (1 \n) TokenInfo(type61 (NL), string\n, start(1, 8), end(1, 9), linea (1 \n) TokenInfo(type2 (NUMBER), string2, start(2, 0), end(2, 1), line2)) TokenInfo(type54 (OP), string), start(2, 1), end(2, 2), line2)) TokenInfo(type4 (NEWLINE), string, start(2, 2), end(2, 3), line) TokenInfo(type0 (ENDMARKER), string, start(3, 0), end(3, 0), line)从上面的解析结果可以看出第一行末尾的换行符(\n)被解析为NL标记而第二行末尾的换行符(\n)被解析为NEWLINE标记。对于上文谈到的其他特性和结果可以自行使用程序进行测试在此不进行详述。7、缩进问题在Python中逻辑行的缩进空格、制表符被当做是层次结构的体现而非逻辑行中的第一行的物理行的缩进则无此效果。a 1 # 该行缩进表示层次结构 b (1 # 该行缩进表示层次结构 2) # 该行缩进不表示层次结构
阅读完成 · 觉得有帮助?
咨询建站