python删除代码注释_删除代码中所有注释(基于文本处理的方法)

处理所有注释,是编译器的看家本领。

编译器在读取代码时,就是在处理文本,自然就包括删除代码注释。

每一个编程语言都有一个叫做词法分析器的工具,编译器就是用它来处理代码文本的,基于正则匹配。它不仅要处理注释,还要处理保留字,标识符等等,要复杂多了

Python中字符"#"只有两种用途,一个是string,字符串,另一个是注释符,用于给代码加入旁白

(但要排除掉python文件头的#!)

即#不能用于其他任何形式,比如标识符,运算符等。

所以思路很明确,判断#是不是字符串,如果不是,那么它后面的所有东西都将被当作注释,直到出现换行符\n。

但这个换行符不是我们可以通过输入 \和n所表示的换行符,只能是我们看不见的换行符,比如敲一下键盘上的Enter。

实际上当我们在字符串中连续输入\和n的时候,(并且只能在字符串中输入),计算机在内部把它们转义成了"\\n"。如果后面你又需要将字符串"\\n" print出来,计算机又把它们当成"\n",并输出字符串里的内容以及格式。而在计算机内部,换行符确实以"\n"(或者深入一点二进制形式)形式存在,但只会以(给文本换行)的方式展现出来,而不会以"\n"的样子展现出来,那个在屏幕上展现出"\n"的样子的东西,在计算机内部以"\\n"的形式存在。

所以以下代码:

a = "a"#这是个注释?"\n"a = "1"

b = "b\nb"#这是个注释?\nb = "2"

print(a)

输出:a (没有引号了,表示引号里面的内容)print(b)

输出:b

b (没有引号了,表示输出引号里面的内容及其格式)

a

输出:'a'(有引号,表示a是字符串)

b

输出:'b\nb'(有引号,表示b是字符串,而不看它里面的转义字符\n)

所以上面代码注释中包含"\n",\n,但它们被计算机读取的时候,都被转义成了"\\n",不具有换行效果。而在a = "1"的后面,真真切切的跟着一个我们看不到的换行符,

#也不是无论如何都看不到,将代码保存到文件D:/code.txt

file= open('D:/code.txt')

file.read()

输出:'a = "a"#这是个注释?"\\n"a = "1"\nb = "b\\nb"#这是个注释?\\nb = "2"'

type(file.read())

输出: str

print(file.read())

输出: a = "a"#这是个注释?"\n"a = "1"

b = "b\nb"#这是个注释?\nb = "2"

说了这么多,就为了可以用#和换行符(看不见的那个)来找出注释。

#和后面第一个换行符中间的所有内容都是注释了。?

非,比如下面代码:

a = "a#a"

print(a)

输出:a#a

要是#a"被当作注释删掉了就不好了。。

前面我们说过,#在python代码中要么以注释符形式存在,要么以字符串形式,上面这个代码就是以字符串形式存在的。字符串,有个很明显的特征:被英文引号(以下简称引号)围住了。

所以,如果代码没有语法错误的话,即能够进入运行期的话,没有被引号括住的行内第一个#,一定是注释符,被引号括住的#,一定不是注释符。

所以思路很明确,先判断#是不是字符串,即没有被引号括住;如果不是,则提取出此#及其之后直到换行符的所有内容,它们就是注释。

但python内置有一个readlines()函数,可以替我们省下找换行符的步骤,它返回一个列表,其中的元素即是文件内容中以换行符隔开的每一行。通过这个函数,我们可以先把代码文件分成一行一行的,再在每一行内寻找注释。需要注意的是,编辑器内自动换行的功能并不是在其中加入了换行符,它们看起来自动换到了下一行,其实在计算机看来还是一行,直到出现换行符。readlines()也不会以我们看到的自动换行的行数为标准,注释符也是,它们只认换行符。

现在就可以开始判断行内的#有没有被引号括住了。

先来探究一下引号的作用机制。

a = "She said, 'All right!'"b= "很明显,',是一个单引号"b_2= '很明显,",是一个双引号'b_3= "很明显,",是一个双引号"#这个会报错SyntaxError

b_4 ='很明显,"",是两个双引号'

c = '"'2'"' #这个会报错SyntaxError

#对于报错,是因为多个同样的引号引起作用范围混淆,解决办法是把里面不参与作用的引号加个\,转义成普通字符,比如c = '"\'2\'"'

首先,计算机从行首第一个字符开始检查,出现双引号,则找第二个双引号,这两个双引号就成双成对了再不会分开了,不会参与后面的双引号作用了,其中的内容也成了一个整体,其中若包含一个引号,比如上面的b,这个引号也不会参与外面的引号作用了。(单引号同理)

所以并不是很复杂,对于readlines()返回的每一行:

1,先看有没有#;

2,如果有,则检查有没有引号;

3,如果有引号,看所有的引号的作用范围是否包括#;

4,如果包括,则继续往后,重复开始第1步;

对于上述每一步,如果遇到了换行符,那么抱歉,检查结束,返回结果。

第1,2,3步的任意一个,结果若为否,则检查完成。

a = ["a#'a", 'b"#"b']#这是个注释?'\n"'a = "1"

将上面这一行代码保存到code.py,然后把code.py当作文本处理。

text = open(文件路径+code.py).read()

text

输出:'a = ["a#\'a", \'b"#"b\']#这是个注释?\'\\n"\'a = "1"'

print(text)

输出:a = ["a#'a", 'b"#"b']#这是个注释?'\n"'a = "1"

可以看到用print(),就跟我们原本的输入一个模样,是代码,不用print()直接查看text,就出来一个字符串,是代码的文本形式,里面的单引号为了不与最两边的单引号发生作用,加了斜杠转义了,而里面的\n是我们自己输入的\和n,并不是用Enter敲出来的换行符,所以计算机只把它们当成普通字符,以\\n的样子存在于计算机内部。

下面代码展示了如何用re正则表达式来提取字符串text中,引号的作用范围

importre

re.split('(".*?"|\'.*?\')', text, maxsplit=0)

输出:['a = [','"a#\'a"',',','\'b"#"b\'',']#这是个注释?','\'\\n"\'','a =','"1"','']

re.split('".*?"|\'.*?\'', text, maxsplit=0)

输出:['a = [',',',']#这是个注释?','a =','']

上述代码用正则表达式匹配到所有的引号作用范围,既考虑单引号,也考虑双引号。

将匹配到的引号作用范围当作分割符,把字符串text分割成若干子串,并返回列表。

第一个split(),比第二个split()的正则表达式里,多了一层小括号,作用是,返回的列表中也要包括分割符。

表达式的中间有个|,|的左右两边一个是匹配双引号的,一个匹配单引号,

即,若只匹配双引号,则使用

re.split('".*?"', text, maxsplit=0)

若只匹配单引号,则使用

re.split('\'.*?\'', text, maxsplit=0)

为什么要给表达式里的单引号加上转义斜杠呢,因为表达式本身用了单引号括住,若不转义为普通字符,则会与本身最外层的引号发生作用。若使用双引号括住,则应该把里面的双引号转义。

maxsplit指定了从左往右分割几次,若为0则不限,若为1,则仅使用第一个引号作用范围来分割成两段,当然如果考虑分割符本身,则是三段。

其它符号如.*?可以艰难参考官方中文文档。

既然确定了引号的作用范围,就能看#是不是引号里面的普通字符了,既然知道了#是普通字符还是注释符,就能找到哪些是注释内容了。

(还是要排除掉python文件头的#!)

其他的如'''''',/**/等注释符,也都是处理文本,道理一个样把。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值