1,复习递归:返回值,不要只看到return就认为已经返回了,要看返回操作是在递归的第几层发生的,然后返回给了谁,如果不是返回给最外层函数,调用者就接收不到,需要再分析,看如何把结果返回回来,超过最大递归限制的报错,只要写递归,必须要有结束条件

2,几乎所有的递归问题都可以用循环来解决问题,只不过有时候,循环考虑的事情更多更复杂,递归会相对少一些,循环写好了,效率有时候会比递归好一点,有时候需要想太多问题,所以就用递归,比如快排,递归和算法联系很紧密,会把问题变简单,效率高。平时递归用的不多,除非,算法分析什么的,如果未来不做这些,工作的很长一段时间都是用不到的。面试有时候会考,递归是非常经典的计算机算法和思想,能看懂,能掌握几个经典的数学算法和概念就可以了

3,作业题一,斐波那契数列递归实现,一定要注意结束条件和传递,递归一般都是结果往前推的

# 1,1,2,3,5,8,13,21,34,55
# 第一种,树性结构
def fib(n):
if n == 1 or n ==2:
return 1 # 结束条件
else:
return fib(n-1) +fib(n-2)
print(fib(10)) # 循环实现
def fib(n):
num1, num2 = 1,1
num = 0
if n==1 or n==2:
return 1
else:
for i in range(n-2):
num = num1 + num2
num1 = num2
num2 = num
return num
print(fib(8)) # 第三种
# 一次调用,那就返回两个值
def fib(n,l=[0]): # 默认参数的陷阱问题,无论发生多少次调用,这个地方都只是用这一个值,利用了这个陷阱问题,在不同的函数调用之间传递值
l[0] +=1
print(l[0])
if n == 1:
return 1
if n ==2 :
l[0]-=1
return 1,1
else:
a,b = fib(n-1)
l[0]-=1
print(l[0]) # 这只是个计数器,计算调用了多少次,最后减完了就可以返回结果了
# a,b = b,a+b
if l[0] == 0:
return a+b
return b,a+b print(fib(11))

4,发生一次调用和两次调用的会非常慢,因为是树形调用,2的n次方和n次的区别

5,作业题二,阶乘,注意fac1001会超过最大递归限制

# 作业题二:阶乘factorial  1 1*2

# 循环实现
def fac(n):
if n == 1:
return 1
else:
b = 1
for i in range(1,n+1):
b = i * b
return b
print(fac(4)) # 递归实现
def fac(n):
if n == 1:
return 1
else:
return n*fac(n-1) print(fac(3))

6,re模块和正则表达式,对比time模块和时间,时间是现实存在的,re模块背后已经存在的就是正则表达式,首先学习正则表达式,然后学习正则表达式操作正则,正则表达式是用来做字符串匹配的,从一大段文章中匹配首先要学习规则,想要Python来做这件事,就要用到re模块。

老师的博客地址:https://www.cnblogs.com/Eva-J/articles/7228075.html#_label10

7,比方说你在注册一个网站,他会检测你输入的格式是不是有问题,这些都是正则来实现的

8,正则规则是客观存在的,世界上任何一种语言都可以有正则的,正则规则在处理字符串上有非常大的优势,正则里面所有的东西,Python里面翻译过来都是字符串,看一个简单的例子

# 判断手机号码是否合法
# 如果是从整个文件里面找出所有符合条件的手机号码,显然这样处理会很麻烦,而正则表达式却可以轻松的处理掉,他有先天的优势
while True:
phone = input("please input you phone number:")
if len(phone) == 11 \
and phone.isdigit() \
and (phone.startswith('')\
or phone.startswith('') \
or phone.startswith('') \
or phone.startswith('')):
print("合法的手机号")
else:
print('不合法') # 正则表达式实现
import re
phone = input("please input you phone number:")
if re.match('^(13|14|15|18)[0-9]{9}$',phone): # 正则规则
print("合法的手机号")
else:
print('不合法')

9,在同一个位置可能出现的字符范围的时候,正则表达式的用武之地就来了

10,用Python来处理正则表达式用到了re模块,三个函数用的最多查找,findall,search,match,

import re

s = 'jasdhfieafy73o84&……%o734yfuye*bfjb98u833242jjxb%'
ret = re.findall('a', s)
# ['a', 'a'],返回所有匹配到的结果放在列表中。
print(ret) ret = re.findall('[a-z]+',s)
print(ret)
# ['jasdhfieafy', 'o', 'o', 'yfuye', 'bfjb', 'u', 'jjxb']

11,search函数返回第一个找到的匹配值

s = 'jasdhfieafy73o84&……%o734yfuye*bfjb98u833242jjxb%'
ret = re.search('a',s)
# <re.Match object; span=(1, 2), match='a'>
print(ret) # 返回一个结果的对象
# 从前往后找到一个就返回需要调用group来拿结果,找不到会返回None,不可以用group来取值,会报错。
print(ret.group())
# a
# 一般情况下我们会,找到值再调用group函数
if ret:
print(ret.group())

12,match函数,必须从头开始匹配

s = 'jasdhfieafy73o84&……%o734yfuye*bfjb98u833242jjxb%'
ret = re.match('a',s) #从头开始匹配,如果正则规则从头开始可以匹配上,就返回一个变量,匹配的内容需要调用group才能显示,
# 如果没有匹配上,就返回None,调用group会报错
print(ret)
# None
ret = re.match('j',s).group()
print(ret)
# j
ret = re.match('ja',s).group()
print(ret)
# ja
if ret:
print(ret.group())

13,split函数,除了查找之外其他的函数

ret = re.split('[ab]','abcd')
print(ret)
# ['', '', 'cd'] # 先按照a分割得到''和'bcd' 再按照b在split ret = re.split('ab','abcd')
print(ret)
# ['', 'cd'] # 按照ab来整体分割

14,sub函数

s = 'fkdjh9845tbfdog7720834y83hdiub'
ret = re.sub('\d','$',s) # 和replace很像,但是replace不能运用正则
print(ret)
print(s) ret = re.sub('\d','$',s,3) # 默认的是全部替换,如果我只想替换指定次数
print(ret)
print(s)

15,subn函数

s = 'fkdjh9845tbfdog7720834y83hdiub'
ret = re.subn('\d','$',s)
print(ret)
# 返回元祖,替换的结果,替换了多少次。

16,compile函数,一次编译,多次运用。将正则表达式编译成为一个正则表达式对象,内置函数也有compile,对一个字符串类型的代码提前进行编译,就可以用eval或者exec来运行了。

正则也是字符串,所以这里的compile和字符串是很像的。

s1 = 'fkdjh9845tbfdog7720834y83hdiub'
s2 = '7720834y83hdiub'
obj = re.compile('\d{3}') #匹配三个数字
ret = obj.search(s1)
if ret:
print(ret.group())
ret = obj.search(s2)
if ret:
print(ret.group()) # 运行结果:
984
772

17,finditer方法,迭代器里面的每一项都需要用i.group来查结果

s = 'fkdjh9845tbfdog7720834y83hdiub'
ret = re.finditer('\d',s) # 返回一个存放匹配结果的迭代器
print(ret) #<callable_iterator object at 0x101eb2278>
print(next(ret).group()) #查看第一个结果
print(next(ret).group()) # 查看第二个结果
print([i.group() for i in ret]) # 查看剩余的所有结果
print('----------------') for i in ret:
print(i.group()) # 迭代器没有强转的过程,上面取过一次了,这儿不再取了

18,group取分组内的内容,用序号来取,这个取分组的机制是由Python决定的,和正则表达式没有关系的,这样的话就感觉比findall好了

import re
ret = re.search('^[1-9]\d{14}(\d{2}[0-9x])?$','')
print(ret.group())
print(ret.group(1)) ret = re.search('^[1-9](\d{14})(\d{2}[0-9x])?$','')
print(ret.group())
print(ret.group(1))
print(ret.group(2)) # 取分组里面的内容 运行结果:
331182199400400500
500
331182199400400500
31182199400400
500

19,findall分组优先和取消分组优先

ret = re.findall('www.(baidu|lisa).com','www.lisa.com')
print(ret) #['lisa']
# 这是因为findall会优先把匹配结果组里的内容返回,如想要要取消分组优先看下面
# 这个规则专门为取消分组优先做的
ret = re.findall('www.(?:baidu|lisa).com','www.lisa.com') # ?:
print(ret) #['www.lisa.com']

20,split函数的分组优先

# 只要有分组,就会特殊对待分组里面的内容
s = 'sdjhfsdig123dfbirisb5df,jbfhj888dnf'
ret = re.split('\d+',s)
print(ret) # ['sdjhfsdig', 'dfbirisb', 'df,jbfhj', 'dnf'] ret = re.split('(\d+)',s) # 加到一个分组里面,会保留切掉的内容
print(ret) # ['sdjhfsdig', '123', 'dfbirisb', '5', 'df,jbfhj', '888', 'dnf']

21,爬虫小练习

# 简单版本
import re
from urllib.request import urlopen def get_page(url):
response = urlopen(url)
return response.read().decode('utf-8') def parse_page(s):
# 这个正则可以对照着html源码来看,re.S匹配空格
ret = re.findall(
'<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>'
'.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>',s,re.S)
return ret def main(num):
url = 'https://movie.douban.com/top250?start=%s&filter=' % num # 这儿是由网址决定的
response_html = get_page(url)
ret = parse_page(response_html)
print(ret) count = 0
for i in range(10): # 10页
main(count)
count += 25

22,爬虫复杂版本,链接,分析图片,登录,这些都是后话,以后再说,宗旨就是爬取下来,分析

# 复杂版本
import re
from urllib.request import urlopen
import json def get_page(url):
response = urlopen(url)
return response.read().decode('utf-8') # 拿到字节码,编码 def parse_page(s):
# 这个正则可以对照着html源码来看,re.S匹配空格,联系上下文的匹配,只要分组里面的内容,利用分组优先,只提取出来,非贪婪匹配,
# 匹配到什么时候为止,分组名指代分组内匹配到的内容,?P就代表给分组取名字
com = re.compile(
'<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>'
'.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>') ret = com.finditer(s,re.S) # 返回迭代器,循环迭代器
for i in ret:
yield {
"id":i.group("id"),
"title":i.group("title"),
"rating_num":i.group("rating_num"),
"comment_num":i.group("comment_num")
} def main(num):
url = 'https://movie.douban.com/top250?start=%s&filter=' % num # 这儿是由网址决定的
response_html = get_page(url)
ret = parse_page(response_html) # 返回的是一个生成器
print(ret)
f = open('move_info7','a',encoding='utf8')
for obj in ret:
print(obj)
data = json.dumps(obj,ensure_ascii=False)
f.write(data+'\n') # json序列化是day20的内容,到时候会有详细的讲解 if __name__ == '__main__':
count = 0
for i in range(10): # 10页
main(count)
count += 25 # url 从网页上把代码爬取下来
# bytes -utf8,网页内容就是待匹配的内容
# ret = re.findall(正则,待匹配的字符串),ret 所有匹配到内容的列表
# 持续爬,过一段时间爬取一次

23,计算器大作业,老师讲解后在更新

# 基本思路:
# 首先得到一个字符串
# 去空格
# 没有空格的字符串
# 先算最里层括号里面的:找括号,且括号里没有括号
# 得到了一个没有括号的表达式:只有加减乘除,从左到右先找到一个乘除法 ---重复
# 所有的乘除法都做完了
# 计算加减 --加减法
# 只有一个数了,就可以结束了

24,计算机大作业,跟着老师讲解自己写的代码

import re

# 计算乘除
def cal_ret_son_1(ret):
if '/' in ret:
new_ret = ret.split('/')
s = str(float(new_ret[0]) / float(new_ret[1]))
return s
elif '*' in ret:
new_ret = ret.split('*')
s = str(float(new_ret[0]) * float(new_ret[1]))
return s # 计算加减 # 这个函数可以简化的其实
def cal_ret_son_2(ret):
if '+' in ret:
new_ret = ret.split('+')
s = str(float(new_ret[0]) + float(new_ret[1]))
return s
elif '-' in ret:
new_ret = ret.split('-')
s = str(float(new_ret[0]) - float(new_ret[1]))
return s # 第三步,计算没有括号的表达式
def cal_express_no_bracket(exp):
exp = exp.strip('()') # 去掉两边的括号 # 先乘除后加减
while True: ret = re.search('\d+\.?\d*[*/]-?\d+\.?\d*', exp)
if ret:
ret_son = ret.group()
s = cal_ret_son_1(ret_son)
exp = exp.replace(ret_son,s)
dealwith_minus(exp)
else:break while True:
exp = dealwith_minus(exp)
ret = re.search('\d+\.?\d*[+\-]-?\d+\.?\d*', exp)
if ret:
ret_son = ret.group()
s = cal_ret_son_2(ret_son)
exp = exp.replace(ret_son, s)
dealwith_minus(exp)
else:break # ret = re.findall('-?\d+\.\d*',exp)
# sum = 0
# for i in ret:
# sum += float(i) return exp # 第三步骤,处理+-连着的这种情况
def dealwith_minus(exp):
if "+-" in exp:
exp = exp.replace('+-','-')
elif "--" in exp:
exp = exp.replace('--','+')
return exp # 第二步 提取括号里面没有其他括号的表达式
# findall search match 三种方法供选择
# findall没有search好,为何呢?比如说3*5*6+2*3 他只能匹配到3*5和2*3,match只能匹配从头开始的
def remove_bracket(new_express):
while True:
express_no_brackets = re.search('\([^()]+\)',new_express) # 中间可以匹配任意多个不是括号的
if express_no_brackets:
express_no_brackets = express_no_brackets.group()
exp = cal_express_no_bracket(express_no_brackets)
new_express = new_express.replace(express_no_brackets,exp)
new_express = dealwith_minus(new_express)
else:
break
ret = cal_express_no_bracket(new_express)
return ret
express = '1 - 2 * ( (60-30 +(-40/5*8) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
print(eval(express)) # 用来验证结果是否正确,会有一点点的误差
# 第一步 去空格
new_express = express.replace(' ','')
print(remove_bracket(new_express)) # 用函数封装以后,代码明显清晰了很多
import re
express = '1 - 2 * ( (60-30 +(-40/5*8) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )' print(eval(express)) # 用来验证结果是否正确,会有一点点的误差
# 第一步 去空格
new_express = express.replace(' ','') # 计算乘除
def cal_ret_son_1(ret):
if '/' in ret:
new_ret = ret.split('/')
s = str(float(new_ret[0]) / float(new_ret[1]))
return s
elif '*' in ret:
new_ret = ret.split('*')
s = str(float(new_ret[0]) * float(new_ret[1]))
return s # 计算加减
def cal_ret_son_2(ret):
if '+' in ret:
new_ret = ret.split('+')
s = str(float(new_ret[0]) + float(new_ret[1]))
return s
elif '-' in ret:
new_ret = ret.split('-')
s = str(float(new_ret[0]) - float(new_ret[1]))
return s # 第三步,计算没有括号的表达式
def cal_express_no_bracket(exp):
exp = exp.strip('()') # 去掉两边的括号 # 先乘除后加减
while True:
dealwith_minus(exp)
ret = re.search('\d+\.?\d*[*/]-?\d+\.?\d*', exp)
if ret:
ret_son = ret.group()
s = cal_ret_son_1(ret_son)
exp = exp.replace(ret_son,s)
else:break while True:
exp = dealwith_minus(exp)
ret = re.search('\d+\.?\d*[+\-]-?\d+\.?\d*', exp)
if ret:
ret_son = ret.group()
s = cal_ret_son_2(ret_son)
exp = exp.replace(ret_son, s)
else:break
return exp # 第三步骤,处理+-连着的这种情况
def dealwith_minus(exp):
if "+-" in exp:
exp = exp.replace('+-','-')
elif "--" in exp:
exp = exp.replace('--','+')
return exp # 第二步 提取括号里面没有其他括号的表达式
# findall search match 三种方法供选择
# findall没有search好,为何呢?比如说3*5*6+2*3 他只能匹配到3*5和2*3,match只能匹配从头开始的 while True:
express_no_brackets = re.search('\([^()]+\)',new_express) # 中间可以匹配任意多个不是括号的
if express_no_brackets:
express_no_brackets = express_no_brackets.group()
exp = cal_express_no_bracket(express_no_brackets)
new_express = new_express.replace(express_no_brackets,exp)
new_express = dealwith_minus(new_express)
else:
break ret = cal_express_no_bracket(new_express)
print(ret)

day18:正则表达式和re模块的更多相关文章

  1. Python之正则表达式(re模块)

    本节内容 re模块介绍 使用re模块的步骤 re模块简单应用示例 关于匹配对象的说明 说说正则表达式字符串前的r前缀 re模块综合应用实例 正则表达式(Regluar Expressions)又称规则 ...

  2. 【转】Python之正则表达式(re模块)

    [转]Python之正则表达式(re模块) 本节内容 re模块介绍 使用re模块的步骤 re模块简单应用示例 关于匹配对象的说明 说说正则表达式字符串前的r前缀 re模块综合应用实例 参考文档 提示: ...

  3. 【Python爬虫】正则表达式与re模块

    正则表达式与re模块 阅读目录 在线正则表达式测试 常见匹配模式 re.match re.search re.findall re.compile 实战练习 在线正则表达式测试 http://tool ...

  4. Python与正则表达式[0] -> re 模块的正则表达式匹配

    正则表达式 / Regular Expression 目录 正则表达式模式 re 模块简介 使用正则表达式进行匹配 正则表达式RE(Regular Expression, Regexp, Regex) ...

  5. python 正则表达式re使用模块(match()、search()和compile())

    摘录 python核心编程 python的re模块允许多线程共享一个已编译的正则表达式对象,也支持命名子组.下表是常见的正则表达式属性: 函数/方法 描述 仅仅是re模块函数 compile(patt ...

  6. 正则表达式之re模块

    re模块一.什么是正则表达式与re模块?1.1 字符组1.2 元字符1.2.1 单个使用1.2.2 组合使用二.为什么要使用正则三.如何使用3.1 re模块的三种比较重要的方法3.1.1 findal ...

  7. python学习笔记(十)——正则表达式和re模块

    #正则表达式和re模块 # match(pattern, string,[flag]) #在字符串开始时进行匹配 # pattern 正则表达式 # string 要匹配的字符串 # [flag] 可 ...

  8. python正则表达式之re模块方法介绍

    python正则表达式之re模块其他方法 1:search(pattern,string,flags=0) 在一个字符串中查找匹配 2:findall(pattern,string,flags=0) ...

  9. day18 python之re模块与正则表达式

    正则表达式 正则表达式,就是匹配字符串内容的一种规则. 官方定义:正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串 ...

随机推荐

  1. CSS3制作图形大全——碉堡了

    为方便观看效果图,请移步原文:https://www.jqhtml.com/8045.html Square   #square {     width: 100px;     height: 100 ...

  2. RabbitMQ 特性

    1RabbitMQ 特点 与 SpringAMQP 完美整合.API 丰富. 集群模式丰富,表达式配置,HA 模式,镜像队列模型. 保证数据不丢失的前提做到高可靠性.可用性.

  3. Cmake find_package 需要指定具体的so

    需要使用cmake的find_package将boost库添加到项目中,通过cmake --help-module FindBoost 可以查看cmake引入Boost的帮助信息: 可以看到,Boot ...

  4. How the heck does async/await work in Python 3.5

    https://snarky.ca/how-the-heck-does-async-await-work-in-python-3-5/

  5. Delphi Format 格式化数字

    Format('x=%d', [12]); //'x=12' //最普通Format('x=%3d', [12]); //'x= 12' //指定宽度Format('x=%f', [12.0]); / ...

  6. 两台linux服务器各有两个不同的用户 其中一个服务器可以无密码登录服务器

    服务器A:普通用户USERA 服务器B:普通用户USERB 把USERA的公钥写入服务器B用户USERB的authorized_keys中 USERA能普能用户登录然后服务器A,然后再登录服务器B: ...

  7. 深入分析 ThreadLocal

    ThreadLoacal是什么? ThreadLocal是啥?以前面试别人时就喜欢问这个,有些伙伴喜欢把它和线程同步机制混为一谈,事实上ThreadLocal与线程同步无关.ThreadLocal虽然 ...

  8. https认证握手过程

  9. 【NLP】MT中BLEU评分机制

    参考博客:https://blog.csdn.net/guolindonggld/article/details/56966200 原著论文:http://www.aclweb.org/antholo ...

  10. 【原创】SAP/Oracle 集团企业海外全球化实施注意事项: 一带一路本地化 (持续更新)

    ABC集团SAP的系统平台已经扩展到全球一百来个国家和地区,SAP系统平台的全球实施项目中, 当时是需要支持当地的业务和法律法规的合规要求. 当时客户也是缺乏当地的资源以及对当地法律法规和业务实践的了 ...