本节大纲:

  1.正则表达式

  2.re模块的学习

  3.速记理解技巧

  4.挑战练习--开发一个简单的python计算器

  5.心得总结

  6.学习建议

正则表达式:

  正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。

  正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。

  特点:    

    1. 灵活性、逻辑性和功能性非常强。
    2. 可以迅速地用极简单的方式达到字符串的复杂控制。
    3. 对于刚接触的人来说,比较晦涩难懂。
 
re模块
  re模块是Python提供对正则表达式支持的一个模块,里面的常用函数为:
  

 re.match 从头开始匹配
re.search 匹配包含
re.findall 把所有匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符当做列表分隔符
re.sub 匹配字符并替换re.sub的参数(表达式规则,新字符串,旧字符串,替换数量为1(count=1))

  常用的正则表达式符号,一般的,基本够用了

 '.'     默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^' 匹配输入字行首,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$' 匹配输入行尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以
'*' 匹配前面的子表达式任意次,re.findall("ab*","cabb3abcbbac") 结果为['abb', 'ab', 'a']
'+' 匹配前面的子表达式一次或多次(大于等于1次),re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
'?' 匹配前面的子表达式零次或一次
'{m}' 匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
'|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c '\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的
'\Z' 匹配字符结尾,同$
'\d' 匹配数字0-9
'\D' 匹配非数字
'\w' 匹配[A-Za-z0-9]
'\W' 匹配非[A-Za-z0-9]
'\s' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t' '(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","").groupdict("city") 结果{'province': '', 'city': '', 'birthday': ''}
 

 速记理解技巧

  

 .
[]
^
$

  上面四个字符是所有语言都支持的正则表达式,所以这四个是基础的正则表达式。正则难理解因为里面有一个等价的概念,这个概念大大增加了理解难度,让很多初学者看起来会懵,如果把等价都恢复成原始写法,自己书写正则就超级简单了,就像说话一样去写你的正则了:

  

等价:
 等价是等同于的意思,表示同样的功能,用不同符号来书写。?,*,+,\d,\w 都是等价字符
  ?等价于匹配长度{0,1}
  *等价于匹配长度{0,}
  +等价于匹配长度{1,}
  \d等价于[0-9]
  \D等价于[^0-9]
  \w等价于[A-Za-z_0-9]
  \W等价于[^A-Za-z_0-9]。
常用运算符与表达式:
  

   ^ 开始
  () 域段
  [] 包含,默认是一个字符长度
  [^] 不包含,默认是一个字符长度
  {n,m} 匹配长度
  . 任何单个字符(\. 字符点)
  | 或
  \ 转义
  $ 结尾
  [A-Z] 26个大写字母
  [a-z] 26个小写字母
  [0-9] 0至9数字
  [A-Za-z0-9] 26个大写字母、26个小写字母和0至9数字 
 
 
分割语法:
  [A,H,T,W] 包含A或H或T或W字母
  [a,h,t,w] 包含a或h或t或w字母
  [0,3,6,8] 包含0或3或6或8数字
语法与释义:
  基础语法 "^([]{})([]{})([]{})$"
  正则字符串 = "开始([包含内容]{长度})([包含内容]{长度})([包含内容]{长度})结束" 
  
  ?,*,+,\d,\w 这些都是简写的,完全可以用[]和{}代替,在(?:)(?=)(?!)(?<=)(?<!)(?i)(*?)(+?)这种特殊组合情况下除外。
  初学者可以忽略?,*,+,\d,\w一些简写标示符,学会了基础使用再按表自己去等价替换

 一些常用的正则表达式例子(摘自百度百科)

 1.验证用户名和密码:("^[a-zA-Z]\w{5,15}$")正确格式:"[A-Z][a-z]_[0-9]"组成,并且第一个字必须为字母6~16位;
2.验证电话号码:("^(\d{3,4}-)\d{7,8}$")正确格式:xxx/xxxx-xxxxxxx/xxxxxxxx;
3.验证手机号码:"^1[3|4|5|7|8][0-9]{9}$";
4.验证身份证号(15位):"\d{14}[[0-9],0-9xX]",(18位):"\d{17}(\d|X|x)";
5.验证Email地址:("^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$");
6.只能输入由数字和26个英文字母组成的字符串:("^[A-Za-z0-9]+$");
7.整数或者小数:^[0-9]+([.][0-9]+){0,1}$
8.只能输入数字:"^[0-9]*$"。
9.只能输入n位的数字:"^\d{n}$"。
10.只能输入至少n位的数字:"^\d{n,}$"。
11.只能输入m~n位的数字:"^\d{m,n}$"。
12.只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"。
13.只能输入有两位小数的正实数:"^[0-9]+(\.[0-9]{2})?$"。
14.只能输入有1~3位小数的正实数:"^[0-9]+(\.[0-9]{1,3})?$"。
15.只能输入非零的正整数:"^\+?[1-9][0-9]*$"。
16.只能输入非零的负整数:"^\-[1-9][0-9]*$"。
17.只能输入长度为3的字符:"^.{3}$"。
18.只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"。
19.只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"。
20.只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。
21.验证是否含有^%&',;=?$\"等字符:"[%&',;=?$\\^]+"。
22.只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"。
23.验证URL:"^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$"。
24.验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:""~""和""~""。
25.验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;""~""、""~""和“30”~“31”。
26.获取日期正则表达式:\\d{4}[年|\-|\.]\d{\1-\12}[月|\-|\.]\d{\1-\31}日?
评注:可用来匹配大多数年月日信息。
27.匹配双字节字符(包括汉字在内):[^\x00-\xff]
评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
28.匹配空白行的正则表达式:\n\s*\r
评注:可以用来删除空白行
29.匹配HTML标记的正则表达式:<(\S*?)[^>]*>.*?</>|<.*? />
评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力
30.匹配首尾空白字符的正则表达式:^\s*|\s*$
评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式
31.匹配网址URL的正则表达式:[a-zA-z]+://[^\s]*
评注:网上流传的版本功能很有限,上面这个基本可以满足需求
32.匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
评注:表单验证时很实用
33.匹配腾讯QQ号:[1-9][0-9]{4,}
评注:腾讯QQ号从10 000 开始
34.匹配中国邮政编码:[1-9]\\d{5}(?!\d)
评注:中国邮政编码为6位数字
35.匹配ip地址:([1-9]{1,3}\.){3}[1-9]。
评注:提取ip地址时有用
36.匹配MAC地址:([A-Fa-f0-9]{2}\:){5}[A-Fa-f0-9]

关于模块的挑战练习

需求:

开发一个简单的python计算器

    1.实现加减乘除及拓号优先级解析
2.用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),
   运算后得出结果,结果必须与真实的计算器所得出的结果一致 tips:
    
   re.search(r'\([^()]+\)',s).group()

    '(-40/5)'

我的代码

 #!/usr/bin/env python
# -*- coding: utf-8 -*-
# This is Jay's work!!
# 2019年4月27日14:45:59 """
心得:
1.一个函数,就应该只实现一个功能
2.[^f]是匹配除中括号里面f的所有字符 ^f是匹配以f开头的字符 [^f]+是匹配除了f中的所有字符
3.re.sub的参数(表达式规则,想替换成啥,被替换的字符串,替换数量)
4.注意科学计数法,一般出现在除法的身上
5.算式前面的负号是一个难受的点
6.乘法中的负负得正也要注意
7.先算乘除,后算加减,但是遇到乘除/加减同级,必须先从左到右依次进行计算
8.re.complie能让程序看起来更简洁,而且运行速度更快
过程:
去掉算式中的空格-->
找到最底层括号的一对算式(-40/5),传给count函数-->
count函数将括号里面的算式进行加减乘除运算,将最后结果(-8.0)返回给变量back-->
将(-8.0)里面的内容提取出来成'-8.0',然后就替换原来算式中的(-40/5)-->
循环上述过程-->
到最后没有括号的时候,就直接用count函数算出结果,替换原来的式子,成为结果 """
import re def multiplication(m):
"""计算乘法"""
# 将算式分开
res = m.split('*')
answer = float(res[0]) * float(res[1]) if float(res[0]) < 0 and float(res[1]) < 0: # 负负得正
answer = '+' + str(answer)
return str(answer) def division(m):
"""计算除法"""
# 将算式分开
res = m.split('/')
answer = float(res[0]) / float(res[1])
if 'e' in str(answer): # 除出来的结果如果是科学计数法
answer = as_num(answer)
return str(answer) def addition(m):
"""计算加法"""
# 将算式分开
res = m.split('+')
answer = float(res[0]) + float(res[1])
return str(answer) def subtraction(m):
"""计算减法"""
# 将算式分开
res = m.split('-')
answer = float(res[0]) - float(res[1])
return str(answer) def as_num(x):
"""这是一个函数,将科学计数法的数据转换成浮点数的功能"""
y = '{:.20f}'.format(x) # 20f表示保留20位小数点的float型
return (y) def count(formula):
"""一个能简单算出加减乘除的函数""" # 下面是乘除法循环
while '*' or '/' in formula:
# 预先将正则表达式的字符串形式编译为实例,这样用着实例的方法,可以加快程序的运行
# 正则表达式:
# '-?[0-9]+\.?[0-9]*' 一个负号或者没有+数字+小数点一个或者没有+数字
# '[\*|\/]' 匹配乘号'*'或者除号'/' 乘号除号都需要转义
# '-?[0-9]+\.?[0-9]*' 一个负号或者没有+数字+小数点一个或者没有+数字 pattern = re.compile('-?[0-9]+\.?[0-9]*[\*|\/]-?[0-9]+\.?[0-9]*')
res = pattern.search(formula)
try: # 若找不到,会有none异常错误,所以在这里抓住一下
if '*' in res.group():
back = multiplication(res.group())
elif '/' in res.group():
back = division(res.group())
except AttributeError:
# print('已经没有算式了')
break
# 用接收回来的结果替换原来的结果
formula = pattern.sub(back, formula, count=1) # 接下来是加减法循环
while '+' or '-' in formula:
# 正则表达式:
# '-?[0-9]+\.?[0-9]*' 一个负号或者没有+数字+小数点一个或者没有+数字
# '[\+|/]' 匹配加好'+'或者减号'-',加好需要转义,减号不需要
# '-?[0-9]+\.?[0-9]*' 一个负号或者没有+数字+小数点一个或者没有+数字 pattern = re.compile('-?[0-9]+\.?[0-9]*[\+|-]-?[0-9]+\.?[0-9]*')
res = pattern.search(formula)
try: # 若找不到,会有none异常错误,所以在这里抓住一下
# print(res.group()) # 最后还会有一个none
if '+' in res.group():
back = addition(res.group())
elif '-' in res.group():
back = subtraction(res.group())
except AttributeError:
# print("已经没有算式了")
break
formula = pattern.sub(back, formula, count=1) # 将计算完的算式,返回给调用函数
return formula def symbol_conversion(formula):
"""这是一个函数,处理负号与正号"""
formula = re.sub('\+-', '-', formula) # 数字前面是'+-'
formula = formula.replace('--', '+') # 数字前面是'--' return formula def find(formula):
"""找到最底层的括号,会成为一个列表,将最底层同级的括号作为一个元素存储"""
# 正则表达式:
# '\([^()]+\)' 匹配最底层括号
# \( \) 两个转义括号 [^()] 里面没有括号
brackets_pattern = re.compile('\([^()]+\)') # 正则表达式:
# '[^((]+(?=[))])' 匹配括号里面的内容
brackets_content = re.compile('[^((]+(?=[))])') res = brackets_pattern.findall(formula)
for i in range(len(res)):
back = count(res[i]) # 替换算式中的结果,并去掉括号,eg:(-40/5)-->(-8.0)
# print(back)
back = brackets_content.findall(back) # 将括号里面的内容取出来
# print(back[0])
formula = formula.replace(res[i], str(back[0])) # 替换算式中的结果,并去掉括号,eg:(-8.0)-->-8.0
formula = symbol_conversion(formula)
print('一轮结果的算式', formula)
return formula if __name__ == '__main__': formula = "1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )"
# formula = input("请输入算式")
# 先去掉空格
formula = formula.replace(' ', '')
print('开始运算前算式', formula)
while '(' in formula:
# 有括号就进行括号的运算
formula = find(formula)
else:
# 没有括号就直接算
formula = count(formula) print("最后的最后的最后的算式为", formula)

心得总结

  这个作业前前后后做了三天,当时刚刚看完re模块的学习视频,觉得大多数功能还是了解的,然后就没尝试去做,觉得应该不难。但是视频里面Alex老师说这个作业挺有挑战性的,如果做了两天都没写出来就不必要写了。现在写完,发现还真是有点挑战性,我说说我写的大致过程吧。

  刚开始,看着需求在发呆,想着如何把底层括号提取出来(当是没看到博客下面有个提示,提取底层括号的正则表达式),就自己硬着头皮在那里写,我早上九点开始写,憋了三个小时,到中午,一点东西都没写出来,真的,是完全没有思路,就连最基本的表达式符号也不知道是干嘛的(+ . * ? ),然后我又去其他博客上面看人家写的,也看不懂。只能硬着头皮,回去再重刷一遍视频,这次我看视频看得无比认真,也没有加快播放速度。

  第二次看完视频,就真的是理解了大概的作用了,然后也看到了博客下面的提示,就可以开始写了,就拿上面的例子算式来写吧,我刚开始提取出来的是(-40/5),觉得这个没难度,因为提取出来的是一个列表,我一个一个的打印出来,看看效果,最终决定将这个(9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) 式子作为切入点,因为里面涵盖了加减乘除。我在写的时候陷进了一个超大的错误误区,我以为先算乘除,可以先算完所有乘法,再算除法,结果是真的天真了,所以在代码的开头我就写上了,同级乘除,必须从左到右。本来按照我的想法,还是挺简单就实现了功能的,一开始先提取所有*号两边的数字,第一次就提取到了(2*5)返回10,其实这样也是错的,数字前面那个负号也是需要提取的,不然返回结果肯定又出差错,然后到算除法的时候,更难受,返回了一个科学计数法的数字,然后下面的正则表达式就报错了,当时我想的是再写了一个正则表达式去提取科学计数法的,后来突然灵光一闪,是不是可以将科学计数法转换为一般形式呢,然后就去疯狂的百度,挺好的,因为当时总算找到了。乘除算完,并替换回原式,我以为接下来的算加减就简单了,就打印一下结果,当时完全没预料到结果返回的是(+-)或者(--),这个没预料到,然后就又写了一个函数去处理这个结果,而且我在每次替换原式的时候都调用这个函数。

  主要就是这几个问题吧,(同级运算,科学计数法,负负得正,负号在数字前面得带着一起运算)在开始写程序的时候,完全没想到的问题,在写的时候就慢慢的露了出来,期间我重构过很多次计算的那个函数,花费了不少精力,而且正则表达式的写,除了找底层括号那个,其他都是自己写出来的。

  对于我贴出来的这个代码,我已经将必要的解释都写了上去,那个代码是最终版的,写完的时候我回头看的时候也看不懂(哈哈),但是那个确实是简洁了,我在下面也贴出我未整理的代码,让你们看看对比,挺乱的,但是那个未整理的代码,我一眼看去就知道逻辑思维,瞬间就能懂得。文章最后是Alex老师的代码。

学习建议

  1.不要总是“我觉得”,你看上面的文字,我是不是用了许多‘我觉得’,这只是为了给你看看当时我多傻,真的,不要太理所当然,写代码是这样,做人也是这样。

  2.在开始写代码之间,最好还是多多思考一下整个的算法流程,就像这个作业,先理清功能:找底层括号-->算括号里面表达式-->结果替换原式-->循环如此

  3.看到程序报错不要慌张,这个是好事,多看一个错误,多一分成长

  4.多多print看程序运行的结果,思考结果的产生

  5.遇到不懂的知识,多多百度谷歌,做好笔记

  6.就算有答案,不到万不得已都别去看,锻炼自己的思维,我在写这个程序,过程中,没看过一眼答案,当写不出正则表达式的时候,有时候我真的很想去看一看答案,但是我每次都忍住了

  7.看懂别人代码是有困难的,我写完之后,花了几分钟去看了看Alex的博客答案,也还是没看懂,但是我还是会去看,学一学别人的逻辑思维

  8.写程序尽量不要停,挑一个安安静静的时间,关掉手机,开开心心地写,我断断续续写了三天,每次从新回到程序的过程中,都非常慢

  9.真的写不出程序的时候,歇一歇,听首歌,回去看看基本语法,会有作用的

  10.不要熬夜一直写,伤身(虽然我有一次写到两点)

我自己能看懂的代码

 #!/usr/bin/env python

 # -*- coding: utf-8 -*-

 # This is Jay's work!!
"""
1.一个函数,就应该只实现一个功能
2.[^f]是匹配除中括号里面f的所有字符 ^f是匹配以f开头的字符 [^f]+是匹配除了f中的所有字符
3.re.sub的参数(表达式规则,想替换成啥,被替换的字符串,替换数量)
4.注意科学计数法
5.算式前面的负号是一个难受的点
6.乘法中的负负得正也要注意
7.先算乘除,后算加减,但是遇到乘除/加减同级,必须先从左到右依次进行计算
"""
import re,string def multiplication(m):
"""计算乘法"""
res = m.split('*')
# print(res)
answer = float(res[0])*float(res[1])
if float(res[0])<0 and float(res[1])<0:
answer ='+' + str(answer)
return answer
def division(m):
"""计算除法"""
res = m.split('/')
print(float(res[0]))
print(float(res[1]))
answer = float(res[0])/float(res[1])
if 'e' in str(answer):
answer = as_num(answer)
return answer
def addition(m):
"""计算加法"""
res = m.split('+')
answer = float(res[0])+float(res[1])
return answer def subtraction(m):
"""计算减法"""
res = m.split('-')
answer = float(res[0]) - float(res[1])
return answer def find_brackets(m):
"""找到最底层的括号""" def as_num(x):
y='{:.20f}'.format(x) # 20f表示保留20位小数点的float型
return(y) def count(formula):
"""先做一个能简单算出加减乘除的函数先"""
print("接收到的算式",formula)
# #先判断乘法的
# print("*"*50)
# if '*' in formula:
# res = re.findall('-?\d+\.?\d*\*-?\d+\.?\d*',formula)
# print("现在的res>>>>>>",res)
# for i in range(len(res)):
# # print("变化之前的i",res[i])
# back = multiplication(res[i]) #算出所有乘法两边的值,然后传回来将本来传过去的那个式子给替换掉
# # print("变化之后的i",back)
# res[i]= back
# # print("not the formula---",formula)
# print("现在的res>>>>>>",res)
# for i in range(len(res)):
# # print(res[i])
# formula = re.sub('-?\d+\.?\d*\*-?\d+\.?\d*',str(res[i]),formula,count=1) #参数(表达式规则,想替换成啥,被替换的字符串,替换数量)
#
# print("look here man..****..",formula)
#
# #再判断除法
# print('/'*50)
# while '/' in formula:
# res = re.search('-?[0-9]+\.?[0-9]*\/[0-9]+\.?[0-9]*',formula)
# print(res.group())
# back = division(res.group())
# print(back)
# formula = re.sub('-?[0-9]+\.?[0-9]*\/[0-9]+\.?[0-9]*',str(back),formula,count=1)
# print("》》》》》》》》》",formula)
#
#
# print('+'*50)
# # if '-' in formula:
# # res = re.search('-[0-9]+\.?[0-9]*',formula)
# # print(res)
# print(formula)
# 来,先判断乘除
print('/*' * 50)
while '*' or '/' in formula:
print('现在进入了乘除法的循环')
print(formula)
res = re.search('-?[0-9]+\.?[0-9]*[\*|\/]-?[0-9]+\.?[0-9]*', formula)
print(res)
try:
print(res.group())
if '*' in res.group():
back = multiplication(res.group())
elif '/' in res.group():
back = division(res.group())
except AttributeError:
print('已经没有算式了')
break
print("乘除法接收的结果", back) formula = re.sub('-?[0-9]+\.?[0-9]*[\*|\/]-?[0-9]+\.?[0-9]*', str(back), formula, count=1)
while '+' or '-' in formula:
print('现在进入了加减法的循环')
res = re.search('-?[0-9]+\.?[0-9]*[\+|-]-?[0-9]+\.?[0-9]*', formula)
print(res)
try:
print(res.group()) #最后还会有一个none
if '+' in res.group():
back = addition(res.group())
elif '-' in res.group():
back = subtraction(res.group())
except AttributeError:
print("已经没有算式了")
break
print(back)
formula = re.sub('-?[0-9]+\.?[0-9]*[\+|-]-?[0-9]+\.?[0-9]*', str(back), formula, count=1)
print("现在的算式为》》》》》》》》》", formula)
else:
print("have done") print('&'*50,formula)
new_formula = formula
return new_formula
# while '-' in formula:
# res = re.search('[0-9]+\.?[0-9]*-[0-9]+\.?[0-9]*', formula)
# print(res.group())
# back = subtraction(res.group())
# print(back)
# formula = re.sub('[0-9]+\.?[0-9]*-[0-9]+\.?[0-9]*', str(back), formula, count=1)
# print("》》》》》》》》》", formula) # if '/' in formula:
# res = re.findall('[0-9]+\.?[0-9]*\/[0-9]+\.?[0-9]*',formula)
# print(res)
# for i in range(len(res)):
# back = division(res[i])
# res[i]=back
# print("现在res又变成了",res)
# for i in range(len(res)):
# print(re.search('[0-9]+\.?[0-9]*\/[0-9]+\.?[0-9]*',formula))
# # formula = re.sub('[0-9]?\.?[0-9]+\/\d+',str(res[i]),formula,count=1) #还有一个"/"没有匹配上
# formula = re.sub('[0-9]+\.?[0-9]*\/[0-9]+\.?[0-9]*',str(res[i]),formula,count=1)
# print("你再看》》》》》",formula)
#
# print('/'*50)
# if '/' in formula:
# res = re.findall('[0-9]*\.?[0-9]+\/[0-9]*\.?[0-9]+',formula)
# print(res)
# for i in range(len(res)):
# back = division(res[i])
# res[i]=back
# print("现在res又变成了",res)
# for i in range(len(res)):
# print(re.search('[0-9]*\.?[0-9]+\/[0-9]*\.?[0-9]+',formula))
# # formula = re.sub('[0-9]?\.?[0-9]+\/\d+',str(res[i]),formula,count=1) #还有一个"/"没有匹配上
# formula = re.sub('[0-9]*\.?[0-9]+\/[0-9]*\.?[0-9]+',str(res[i]),formula,count=1)
# print("你再看》》》》》",formula)
# print('+'*50) # #下面开始算加
# while '+' in formula:
# res = re.findall('[0-9]+\.?[0-9]*\+[0-9]+\.?[0-9]*',formula)
# print(res)
# for i in range(len(res)):
# back = addition(res[i])
# res[i] = back
#
# for i in range(len(res)):
# formula= re.sub('[0-9]+\.?[0-9]*\+[0-9]+\.?[0-9]*',str(res[i]),formula,count=1)
# print("你再看》》》》》", formula)
#
# #下面开始算减法
# print("-"*50)
# if '-' in formula:
# res = re.findall('[0-9]+\.?[0-9]*-[0-9]+\.?[0-9]*',formula)
# print(res)
# for i in range(len(res)):
# back = subtraction(res[i])
# res[i] = back
#
# for i in range(len(res)):
# formula = re.sub('[0-9]+\.?[0-9]*-[0-9]+\.?[0-9]*',str(res[i]),formula,count=1)
# print("你再看》》》》》", formula)
# s = "1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )"
#先去掉空格
s = s.replace(' ','')
res = re.findall('\([^()]+\)',s)
# print(res[3])
# count(res[3]) for i in range(len(res)):
back = count(res[i])
print(back)
back = re.findall('[^((]+(?=[))])',back)
print(back[0])
s = s.replace(res[i],str(back[0]))
print("最后算式是",s) s = re.sub('\+-','-',s)
s = s.replace('--','+') print('第一轮结果的算式',s) res = re.findall('\([^()]+\)',s)
for i in range(len(res)):
back = count(res[i])
print(back)
back = re.findall('[^((]+(?=[))])',back)
print(back[0])
s = s.replace(res[i],str(back[0]))
print("最后算式是",s) s = re.sub('\+-','-',s)
s = s.replace('--','+') print('第二轮结果的算式',s)
# print(res) res = re.findall('\([^()]+\)',s)
for i in range(len(res)):
back = count(res[i])
print(back)
back = re.findall('[^((]+(?=[))])',back)
print(back[0])
s = s.replace(res[i],str(back[0]))
print("最后算式是",s) s = re.sub('\+-','-',s)
s = s.replace('--','+') print('第三轮结果的算式',s) print(re.findall('\([^()]+\)',s))
count(s) # print('look the space',''.join(s.split())) #两种方法去掉字符串中所有的空格
# print('look the space',s.replace(' ','')) # s = '1+(3+4*(4+2))-(4-3*3)'
# print(s)
#
# res = re.findall('\([^()]+\)',s)
# print(re.findall('[^()]',s))
# print(res)
#
# print(re.findall('[^f]',s))
#
#
#
#

大神Alex的代码--->https://www.cnblogs.com/alex3714/articles/5169958.html

小白学习Python之路---re模块学习和挑战练习的更多相关文章

  1. 小白的Python之路 day1 模块初识

    模块初识 Python的强大之处在于他有非常丰富和强大的标准库和第三方库,几乎你想实现的任何功能都有相应的Python库支持,以后的课程中会深入讲解常用到的各种库,现在,我们先来象征性的学2个简单的. ...

  2. 小白的Python之路 day5 模块XML特点和用法

    模块XML的特点和用法 一.简介 xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今 ...

  3. (转)Python之路,Day6 - 面向对象学习

    本节内容:   面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法.     引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战> ...

  4. Python 日期时间处理模块学习笔记

    来自:标点符的<Python 日期时间处理模块学习笔记> Python的时间处理模块在日常的使用中用的不是非常的多,但是使用的时候基本上都是要查资料,还是有些麻烦的,梳理下,便于以后方便的 ...

  5. 小白学习Python之路---开发环境的搭建

    本节内容 1.Python的介绍 2.发展史 3.安装Python 4.搭建开发环境 5.Hello World程序 一.Python的介绍 Python的创始人为荷兰人吉多·范罗苏姆(Guido v ...

  6. Python全栈之路----常用模块学习----模块的种类和导入方法

    什么是模块? 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码 ...

  7. Day5 - Python基础5 常用模块学习

    Python 之路 Day5 - 常用模块学习   本节大纲: 模块介绍 time &datetime模块 random os sys shutil json & picle shel ...

  8. Python之路,入门学习(一)

    一.变量\字符编码 声明变量 #_*_coding:utf-8_*_ name = "Alex Li" 上述代码声明了一个变量,变量名为: name,变量name的值为:" ...

  9. python中的xlrd模块学习

    1.xlrd模块主要用于excel表格的读取,支持xlsx和xls:xlwt主要用于excel的写,库的读取 2.常用单元格中的数据类型 0.empty(空的):1.string(text):2.nu ...

随机推荐

  1. nginx基本配置参数说明

    #运行用户 user nobody; #启动进程,通常设置成和cpu的数量相等 worker_processes 1; #全局错误日志及PID文件 #error_log logs/error.log; ...

  2. Flex 对Xml对象操作

    一.读取.xml文件() import flash.events.Event;   import flash.net.URLLoader;   import flash.net.URLRequest; ...

  3. Java容器:List

    集合类的层次关系 List接口简介 List的常用方法 List实例 Vector ArrayList Vector和ArrayList的扩容 LinkedList 参考文章 今天开始更新Java集合 ...

  4. Spring HTTP状态码枚举值对照表

    使用Spring时总去查HTTP状态码对应的Spring枚举值的那篇代码,有点不方便,把代码拷贝出来统一替换格式做成了表格,放在这里,方便大家使用.(枚举类为HttpStatus) 枚举值 HTTP状 ...

  5. MySQL技术内幕 InnoDB存储引擎(笔记)

    1. InnoDB 体系架构 其中,后台程序主要负责刷新内存池中的数据,保证缓冲池中的内存缓存的是最近的数据. 此外将已经修改的数据刷新到磁盘文件,同时保证在数据库发生异常的时候Innodb能恢复正常 ...

  6. Flask入门之Pycharm写Hello Word

    在这里记录整理Flask入门的笔记! 今天讲讲使用Pycharm写一个Hello World 前提是已经安装好Pycharm,安装过程很简单,这里不赘述. 只放两个可以提供注册码的网站: Intell ...

  7. QT5:C++实现基于multimedia的音乐播放器(一)

    上一篇里简略的描述了一下播放器的实现,这一篇开始具体描述一下过程. 环境配置:Qt Creator 打开Qt Creator,创建一个new project,项目名称随你喜欢(我的是MusicPlay ...

  8. ReenTrantLock可重入锁(和synchronized的区别)总结

    ReenTrantLock可重入锁(和synchronized的区别)总结 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也 ...

  9. String的charAt(int index)可用于遍历一个字符串的所有字符

    charAt(int index)遍历一个字符串的所有字符实例 String name = "Whatisjava?"; for (int i = 0; i < name.l ...

  10. form表单发送请求实例

    <%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncodi ...