1,
#递归函数
# 了解什么是递归 : 在函数中调用自身函数
# 最大递归深度默认是997/998 —— 是python从内存角度出发做得限制
#RecursionError: maximum recursion depth exceeded while calling a Python object
# 递归的错误,超过了递归的最大深度
# import sys
# sys.setrecursionlimit(1000000)
# n = 0
# def story():
# global n
# n += 1
# print(n)
# story()
# story()
# 如果递归次数太多,就不适合使用递归来解决问题
# 递归的缺点 : 占内存
# 递归的优点: 会让代码变简单
# alex 多大 n = 1 age(1) = age(2)+2 = age(n+1) + 2
# alex比egon大两岁
# egon多大? n = 2 age(2) = age(3) + 2 = age(n+1) +2
# egon比wusir大两岁
# wusir多大 n = 3 age(3) = age(4) + 2 = age(n+1) +2
# wusir比金老板大两岁
# 金老板多大?
# 金老板40了 n = 4 age(4) = 40
# n = 4 age(4) = 40
# n <4 age(n) = age(n+1) +2
def age(n):
if n == 4:
return 40
elif n >0 and n < 4:
age(n+1) + 2
#
print(age(1))
2,递归函数,每个调用结果都用return返回,防止返回不回值
# 二分查找算法 必须处理有序的列表
# l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
def find(l,aim,start = 0,end = None):
end = len(l) if end is None else end
mid_index = (end - start)//2 + start
if start <= end:
if l[mid_index] < aim:
return find(l,aim,start =mid_index+1,end=end)
elif l[mid_index] > aim:
return find(l, aim, start=start, end=mid_index-1)
else:
return mid_index
else:
return '找不到这个值'
ret= find(l,44)
print(ret)
一个递归函数中,应避免分拆成2个及以上的递归调用。应该直线式调用
3,正则表达式
http://tool.chinaz.com/regex/
re模块
import re
[A-Za-z0-9]字母和数字,可同时放n个字符组
代码 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线word |
\s | 匹配任意的空白符space |
\d | 匹配数字digit |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
代码/语法 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
代码/语法 | 说明 |
---|---|
\W | 匹配任意不是字母,数字,下划线,汉字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字的字符 |
\B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 |
.\b
限定符要放在元字符后面,且只对贴在一起的最近的元字符有效
\w+\d+ #前面的+只对字母有效,后面的+只对数字有效
\d{11} #匹配有11位长度的数字
\\n 匹配\n
.*?要与其它字符配合写(贪婪匹配),如:
<.*?> 匹配<script><scewe32ript>这2项 # 加上?为将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串
.*?x 匹配任意长度字符,直到遇到x字符,就匹配完成
r'\\n' 匹配r'\n' # 在字符串之前加r,让整个字符串不转义
?是特别限定符:
1) 限定符后加?,取最少的动作,即惰性运算;2)用?:取消权限
4,
# ret = re.findall('[a-z]+', 'eva egon yuan')
# # 返回所有满足匹配条件的结果,放在列表里
# print(ret) #输出 ['eva', 'egon', 'yuan']
# ret = re.search('a', 'eva egon yuan')
# if ret:
# print(ret.group())
# 从前往后,找到第一个就返回,返回的变量需要调用group才能拿到结果
# 如果没有找到,那么返回None,调用group会报错
# ret = re.match('[a-z]+', 'eva egon yuan')
# if ret:
# print(ret.group()) #输出:eva
# match是从头开始匹配,如果正则规则从头开始可以匹配上,就返回第一个匹配的变量。
# 匹配的内容需要用group才能显示
# 如果没匹配上,就返回None,调用group会报错
# ret = re.split('[ab]', 'abcd')
# # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
# print(ret) #输出: ['', '', 'cd']
# ret = re.sub('\d', 'H', 'eva3egon4yuan4',1)
#将数字替换成'H',参数1表示只替换1个(从左往右数)
# print(ret) #evaHegon4yuan4
# ret = re.subn('\d', 'H', 'eva3egon4yuan4',2)
# #将数字替换成'H',返回元组(替换的结果,替换了多少次)
# print(ret) #输出:('evaHegonH5yuan2', 2)
# obj = re.compile('\d{3}')
# #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
# ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串
# print(ret.group()) #结果 : 123
# ret = obj.search('abcashgjgsdghkash456eeee3wr2') #正则表达式对象调用search,参数为待匹配的字符串
# print(ret.group()) #结果 : 456
# import re
# ret = re.finditer('\d', 'ds3sy4784a') #finditer返回一个存放匹配结果的迭代器
# print(ret) # <callable_iterator object at 0x10195f940>
# # print(next(ret).group()) #查看第一个结果
# # print(next(ret).group()) #查看第二个结果
# # print([i.group() for i in ret]) #查看剩余的左右结果
# for i in ret:
# print(i.group())
上述函数的flag
flags有很多可选值:
re.I(IGNORECASE)忽略大小写,括号内是完整的写法
re.M(MULTILINE)多行模式,改变^和$的行为 re.S(DOTALL)点可以匹配任意字符,包括换行符 re.L(LOCALE)做本地化识别的匹配,表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境,不推荐使用 re.U(UNICODE) 使用\w \W \s \S \d \D使用取决于unicode定义的字符属性。在python3中默认使用该flag re.X(VERBOSE)冗长模式,该模式下pattern字符串可以是多行的,忽略空白字符,并可以添加注释
如:def findall(pattern, string, flags=0)
5,分组 ()与 或 |[^]
import re
# ret = re.search('^[1-9](\d{14})(\d{2}[0-9x])?$','110105199912122277')
# print(ret.group())
# print(ret.group(1))
# print(ret.group(2))
# import re
#
# ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
# print(ret) # 输出:['oldboy'] 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
#
# ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com') #用?:取消权限
# print(ret) #结果 : ['www.oldboy.com']
ret=re.split("\d+","eva3egon4yuan")
print(ret) #结果 : ['eva', 'egon', 'yuan']
ret=re.split("(\d+)","eva3egon4yuan",re.S)
print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan']分隔部分一起输出
6,匹配标签
import re ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>") #还可以在分组中利用?<name>的形式给分组起名字 #获取的匹配结果可以直接用group('名字')拿到对应的值 print(ret.group('tag_name')) #结果 :h1 print(ret.group()) #结果 :<h1>hello</h1> ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>") #如果不给组起名字,也可以用\序号来找到对应的组,表示要找的内容和前面的组内容一致 #获取的匹配结果可以直接用group(序号)拿到对应的值 print(ret.group(1)) print(ret.group()) #结果 :<h1>hello</h1>
7,
三级菜单
menu = { '北京': { '海淀': { '五道口': { 'soho': {}, '网易': {}, 'google': {} }, '中关村': { '爱奇艺': {}, '汽车之家': {}, 'youku': {}, }, '上地': { '百度': {}, }, }, '昌平': { '沙河': { '老男孩': {}, '北航': {}, }, '天通苑': {}, '回龙观': {}, }, '朝阳': {}, '东城': {}, }, '上海': { '闵行': { "人民广场": { '炸鸡店': {} } }, '闸北': { '火车战': { '携程': {} } }, '浦东': {}, }, '山东': {}, } menu
def threeLM(dic): while True: for k in dic:print(k) key = input('input>>').strip() if key == 'b' or key == 'q':return key elif key in dic.keys() and dic[key]: ret = threeLM(dic[key]) if ret == 'q': return 'q' threeLM(menu) 递归函数实现三级菜单
学习:
https://www.cnblogs.com/Eva-j/articles/7228075.html#_label10
a = '1 - 2 * ( ( 6 0 -3 0 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
import re def compu(lin): '''计算字符串中的数字''' ret2 = re.findall('(?:-?\d+\.\d+)|(?:-?\d+)', lin) # 拿到所有数字 # print(ret2, len(ret2)) com_alpha = re.findall('[(\+)|\-|(\*)|/]', lin[1:]) # 拿到所有运算符 # print(com_alpha, len(com_alpha)) count = 0 com_alpha_new = [] ret2_new = [] flag_multiply = False temp = 0 if '*' in com_alpha or '/' in com_alpha: while count < len(com_alpha): # 乘除运算后的数字,放到新列表中 if com_alpha[count] == '*': if flag_multiply == False: temp = float(ret2[count]) * float(ret2[count + 1]) flag_multiply = True else: temp = temp * float(ret2[count + 1]) elif com_alpha[count] == '/': if flag_multiply == False: temp = float(ret2[count]) / float(ret2[count + 1]) flag_multiply = True else: temp = temp / float(ret2[count + 1]) else: if flag_multiply: ret2_new.append(temp) # temp数字(乘除运算完成)放到新列表中 com_alpha_new.append(com_alpha[count]) flag_multiply = False else: ret2_new.append(ret2[count]) com_alpha_new.append(com_alpha[count]) # +-运算符没有运算,原样放到新列表中 count += 1 if flag_multiply: ret2_new.append(temp) # 循环后最后一个temp数字(乘除运算完成)放到新列表中 flag_multiply = False ret2 = ret2_new com_alpha = com_alpha_new # print(ret2, com_alpha) if len(ret2) > 1: sum_result = 0.0 flag_add = False for i in ret2: # 开始加法运算,不用关心列表中的运算符是否是减号 sum_result += float(i) ret2 = sum_result return ret2[0] if type(ret2) is list else ret2 # 返回的是float类型值 def partition_right(a): '''对运算符进行)圆括号分拆 由partition()函数调用''' ret = re.split('\)', a,1) # 否则,对第一个)进行分拆,生成list值 # ret2 = re.split('\)', a,1) print(ret,'---partition_right') ret[0] = str(compu(ret[0])) ret = ')'.join(ret) print(ret,'---partition_right') return ret # 第1个)左边的数计算后的,以及没有计算的字符串,连接后返回 def partition(a): '''对运算符进行圆括号分拆 需调用partition_right(a)函数''' if '(' not in a: # 如没有(,进行第1个)左边的字符串计算 ret = partition_right(a) else: # 否则,是含()的完整运算符 ret = re.split('\(', a) # 对所有)进行分拆,生成list值 ret2 = re.split('\(', a) print(ret,'---partition') count = 0 for i in ret: if ')' in i: # 说明是(分拆部分,进行运算 ret_new = re.split('\).*?', i, 1) # 找到小括号的最里层 # print(ret_new) temp = compu(ret_new[0]) ret_new[0] = str(temp) # 运算结果不管正负,去掉一个)括弧 ret_new = ''.join(ret_new) ret[count] = ret_new # print(ret_new, '-' * 10) count += 1 print(ret, '#' * 10) count = len(ret) - 1 ret_new = '' while count >= 0: # 从最右边开始合并运算字符串 if ret_new == '': ret_new = ret[count] elif ret[count] == '': # single_digit = len(re.findall('(?:-?\d+\.\d+)|(?:-?\d+)', ret[count + 1])) if (ret[count-1][-1] in '+-*/') and (ret[count+1] != ret2[count+1]): # 看后面数字有没有运算过 ret_new = '(' + ret_new # 运算过就去掉一个( else: ret_new = ret[count] + '((' + ret_new elif ret_new[0] != '-': # 判断后面的数如是正数,直接跟前面连接 ret_new = ret[count] + ret_new else: # 后面的数如是负数 single_digit = len(re.findall('(?:-?\d+\.\d+)|(?:-?\d+)', ret[count+1])) if ret[count][-1] in '+-*/' and single_digit != 1: # 如前面是运算符,后面不是单一数字 temp = re.split('\)', ret_new, 1) ret_new = '))'.join(temp) ret_new = ret[count] + '(' + ret_new # 补上() elif ret[count][-1] == '+': # 如后面是单一数字 temp = re.split('\)', ret_new, 1) ret_new = ')'.join(temp) ret_new = ret[count][:-1] + ret_new # 负负得正后连接 elif ret[count][-1] == '-': # 如后面是单一数字 temp = re.split('\)', ret_new, 1) ret_new = ')'.join(temp) ret_new = ret[count][:-1] + '+' + ret_new[1:] # 负负得正后连接 elif ret[count][-1] in '/*': # 如后面是单一数字,前面是乘除运算 single_digit = len(re.findall('(?:-?\d+\.\d+)|(?:-?\d+)', ret[count])) # 前面是否是单一数字 if single_digit > 1: # 前面是多个数字的运算 count2 = len(ret[count]) flag = False while flag == False: count2 -= 1 # 当flag为True时,count2就是+或-的索引号 if ret[count][count2] in '+-': flag = True if ret[count][count2] == '+': temp = ret[count][:count2] temp = temp + '-' + ret[count][count2 + 1:] ret[count] = temp else: temp = ret[count][:count2] temp = temp + '+' + ret[count][count2 + 1:] ret[count] = temp else: # 单一数字 if ret[count][0] == '-': ret[count][0] = ret[count][1:] else: ret[count] = '-' + ret[count] ret_new = ret[count] + ret_new[1:] count -= 1 ret = ret_new print(ret) # 新的完整运算字符串 if '(' not in ret: temp = re.search('[(\+)|\-|(\*)|/]',ret) if temp: return compu(ret) else: # 运算过最内层()后,运算上一层的() return partition(ret) a = '1 - 2 * ( ( 6 0 -3 0 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )' a = a.replace(' ','') print(a) print(partition(a))
耗费了元旦假3天。。。