递归、匿名函数、内置函数
递归
递归调用是函数嵌套调用的一种特殊形式。函数在调用的时候,直接或者间接的调用了自身。
比如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#直接调用本身 def f1(): print('from f1') f1() f1() #间接调用本身 def f1(): print('from f1') f2() def f2(): print('from f2') f1() f1() # 调用函数会产生局部的名称空间,占用内存,因为上述这种调用会无需调用本身,python解释器的内存管理机制为了防止其无限制占用内存,对函数的递归调用做了最大的层级限制 四 可以修改递归最大深度 import sys sys.getrecursionlimit() sys.setrecursionlimit(2000) def f1(n): print('from f1',n) f1(n+1) f1(1) 虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归,而且无限制地递归调用本身是毫无意义的,递归应该分为两个明确的阶段,回溯与递推
递归调用应该分为两个明确的阶段:递推和回溯
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#1、递归调用应该包含两个明确的阶段:回溯,递推 回溯就是从外向里一层一层递归调用下去, 回溯阶段必须要有一个明确地结束条件,每进入下一次递归时,问题的规模都应该有所减少(否则,单纯地重复调用自身是毫无意义的) 递推就是从里向外一层一层结束递归 #2、示例+图解。。。 # salary(5)=salary(4)+300 # salary(4)=salary(3)+300 # salary(3)=salary(2)+300 # salary(2)=salary(1)+300 # salary(1)=100 # # salary(n)=salary(n-1)+300 n>1 # salary(1) =100 n=1 def salary(n): if n == 1: return 100 return salary(n-1)+300 print(salary(5))
递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
补充:二分法
想从一个按照从小到大排列的数字列表中找到指定的数字,遍历的效率太低,用二分法(算法的一种,算法是解决问题的方法)可以极大低缩小问题规模
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
l=[1,2,10,30,33,99,101,200,301,311,402,403,500,900,1000] #从小到大排列的数字列表 def search(n,l): print(l) if len(l) == 0: print('not exists') return mid_index=len(l) // 2 if n > l[mid_index]: #in the right l=l[mid_index+1:] search(n,l) elif n < l[mid_index]: #in the left l=l[:mid_index] search(n,l) else: print('find it') search(3,l) # 优化后—————————————————————— l=[1,2,10,30,33,99,101,200,301,402] def search(num,l,start=0,stop=len(l)-1): if start <= stop: mid=start+(stop-start)//2 print('start:[%s] stop:[%s] mid:[%s] mid_val:[%s]' %(start,stop,mid,l[mid])) if num > l[mid]: start=mid+1 elif num < l[mid]: stop=mid-1 else: print('find it',mid) return search(num,l,start,stop) else: #如果stop > start则意味着列表实际上已经全部切完,即切为空 print('not exists') return search(301,l)
匿名函数
匿名函数就是没有名字
比如:
lambda x,y,z=1:x+y+z
匿名函数和普通函数有相同的作用域。而且没有return,结构较为简单,只能放一个执行语句。
匿名意味着引用计数为0,使用就释放了,除非有名字指向它。
比如:
func=lambda x,y,z=1:x+y+z print(func(1,2,3)) # 6
匿名函数常用于内置函数:max,min,sorted,map,reduce,filter
内置函数
#注意:内置函数id()可以返回一个对象的身份,返回值为整数。这个整数通常对应与该对象在内存中的位置,但这与python的具体实现有关,
不应该作为对身份的定义,即不够精准,最精准的还是以内存地址为准。is运算符用于比较两个对象的身份,等号比较两个对象的值,
内置函数type()则返回一个对象的类型 #更多内置函数:https://docs.python.org/3/library/functions.html?highlight=built#ascii
map函数
格式:
map(参数1,参数2)
map中第一个参数是函数,第二个参数是一个可迭代对象。这个可迭代对象会逐个带入到函数中进行处理。返回的结果是一个map对象。
注意:如果是再python2中,返回的就是一个列表对象
比如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
s = "中华人民共和国" print(map(lambda x:x.upper(), s)) print(type(map(lambda x:x.upper(), s))) # <class 'map'> print(list(map(lambda x:x.upper(), s))) # ['中', '华', '人', '民', '共', '和', '国'] # 例子中我将其转为一个列表显示。
filter函数
和map函数格式一致,只不过第一个参数的结果转换为布尔值,将布尔值为真的挑选出来,返回的是一个filter对象
比如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
a = [13, 342, 4532, 51, 1, 3, 6] res = filter(lambda n: not n < 20, a) print(type(res)) # <class 'filter'> print(list(res)) # [342, 4532, 51]
reduce函数
格式:
from functools import reduce reduce(参数1,参数2,参数3)
参数2为可迭代对象,将参数2带入到参数1中进行运算,如果有额外元素的话,运算的话可以加入参数3
比如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from functools import reduce num_l = ["11", "22", "33"] print(reduce(lambda x, y: x+y, num_l, "**")) # **112233 print(reduce(lambda x, y: x+y, num_l)) # 112233 -------------------------------------------------------------- from functools import reduce num_l=[1, 2, 3, 100] print(reduce(lambda x, y: x+y, num_l, 1)) # 107 print(reduce(lambda x, y: x+y, num_l)) # 106
zip函数
格式:
zip(参数1,参数2)
参数必须是序列类型(列表,元组,字符串),zip函数会将两个参数一一对应放在一个元组中,返回的是一个zip对象
比如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
res = zip(("a", "n", "c"), (1, 2, 3)) print(type(res)) # <class 'zip'> print(list(res)) # [('a', 1), ('n', 2), ('c', 3)] p = {"张三": 20, "李四": 30, "王五": 40, } print(list(zip(p.values(), p.keys()))) # [(20, '张三'), (30, '李四'), (40, '王五')]
max、min函数
max函数和min函数处理数据的时候,相当于处理可迭代对象,相当于用for循环取出每一个元素进行比较。需要注意的是:不同类型不能进行比较。比较字符串的时候,是先比较第一位,如果相同再继续比较,最后得出结果。
max函数和min函数如果要处理其他的数据比较很简单,但是要比较字典的话,可以用上面说到的zip函数将字典改变成value在前,key在后的形式,然后强转成字典,用max函数和min函数比较。这两个函数在比较字典的时候是比较字典的key的,所有可以利用这个特性。
max函数和min函数中,还有可以指定一个方法,用key关键字传递给max进行处理
比如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
p = {"张三": 20, "李四": 30, "王五": 40, } res = dict(zip(p.values(), p.keys())) print(res) # {40: '王五', 20: '张三', 30: '李四'} print(max(res)) # 40
还有一种形式就是将容器中的字典内容进行比较:
比如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
p = [ {"name": "张三", "age": 20}, {"name": "赵四", "age": 30}, {"name": "王五", "age": 40}, {"name": "钱六", "age": 50} ] print(max(p, key=lambda dic: dic['age'])) # {'age': 50, 'name': '钱六'}
slice函数
slice函数可以定义切片的设置,然后传给切片。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
l = "中华人民共和国" s1 = slice(3, 5, 2) print(l[s1]) # 民 print(s1.start) # 3 print(s1.stop) # 5 print(s1.step) # 2
eval函数
eval函数有两个功能,第一个是:将字符串中的数据结构提取出来。第二个是:将字符串中的表达式计算
例如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
res = eval("[1, 3, 4,]") print(res) # [1, 3, 4] print(eval("2*3*3")) # 18
format函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#字符串可以提供的参数 's' None >>> format('some string','s') 'some string' >>> format('some string') 'some string' #整形数值可以提供的参数有 'b' 'c' 'd' 'o' 'x' 'X' 'n' None >>> format(3,'b') #转换成二进制 '11' >>> format(97,'c') #转换unicode成字符 'a' >>> format(11,'d') #转换成10进制 '11' >>> format(11,'o') #转换成8进制 '13' >>> format(11,'x') #转换成16进制 小写字母表示 'b' >>> format(11,'X') #转换成16进制 大写字母表示 'B' >>> format(11,'n') #和d一样 '11' >>> format(11) #默认和d一样 '11' #浮点数可以提供的参数有 'e' 'E' 'f' 'F' 'g' 'G' 'n' '%' None >>> format(314159267,'e') #科学计数法,默认保留6位小数 '3.141593e+08' >>> format(314159267,'0.2e') #科学计数法,指定保留2位小数 '3.14e+08' >>> format(314159267,'0.2E') #科学计数法,指定保留2位小数,采用大写E表示 '3.14E+08' >>> format(314159267,'f') #小数点计数法,默认保留6位小数 '314159267.000000' >>> format(3.14159267000,'f') #小数点计数法,默认保留6位小数 '3.141593' >>> format(3.14159267000,'0.8f') #小数点计数法,指定保留8位小数 '3.14159267' >>> format(3.14159267000,'0.10f') #小数点计数法,指定保留10位小数 '3.1415926700' >>> format(3.14e+1000000,'F') #小数点计数法,无穷大转换成大小字母 'INF' #g的格式化比较特殊,假设p为格式中指定的保留小数位数,先尝试采用科学计数法格式化,得到幂指数exp,如果-4<=exp<p,则采用小数计数法,并保留p-1-exp位小数,否则按小数计数法计数,并按p-1保留小数位数 >>> format(0.00003141566,'.1g') #p=1,exp=-5 ==》 -4<=exp<p不成立,按科学计数法计数,保留0位小数点 '3e-05' >>> format(0.00003141566,'.2g') #p=1,exp=-5 ==》 -4<=exp<p不成立,按科学计数法计数,保留1位小数点 '3.1e-05' >>> format(0.00003141566,'.3g') #p=1,exp=-5 ==》 -4<=exp<p不成立,按科学计数法计数,保留2位小数点 '3.14e-05' >>> format(0.00003141566,'.3G') #p=1,exp=-5 ==》 -4<=exp<p不成立,按科学计数法计数,保留0位小数点,E使用大写 '3.14E-05' >>> format(3.1415926777,'.1g') #p=1,exp=0 ==》 -4<=exp<p成立,按小数计数法计数,保留0位小数点 '3' >>> format(3.1415926777,'.2g') #p=1,exp=0 ==》 -4<=exp<p成立,按小数计数法计数,保留1位小数点 '3.1' >>> format(3.1415926777,'.3g') #p=1,exp=0 ==》 -4<=exp<p成立,按小数计数法计数,保留2位小数点 '3.14' >>> format(0.00003141566,'.1n') #和g相同 '3e-05' >>> format(0.00003141566,'.3n') #和g相同 '3.14e-05' >>> format(0.00003141566) #和g相同 '3.141566e-05'
exec函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# exec:三个参数 # 参数一:包含一系列python代码的字符串 # 参数二:全局作用域(字典形式),如果不指定,默认为globals() # 参数三:局部作用域(字典形式),如果不指定,默认为locals() # 可以把exec命令的执行当成是一个函数的执行,会将执行期间产生的名字存放于局部名称空间中 g = { 'x': 1, 'y': 2 } l = {} exec(''' global x,z x=100 z=200 m=300 ''', g, l) print(g) # {'x': 100, 'y': 2,'z':200,......} print(l) # {'m': 300} # 说明:即使是在三引号中也要注意缩进问题。
其他内置函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
abs():求绝对值 all():只能给一个参数,里面参数都为真(类似列表的,是列表中的每个元素,真则要注意哪些情况下布尔值为真),返回True,否则返回False, bytes(参数,encoding="utf-8"):将参数转为指定的编码格式。 chr():将整数转成对应的字符 ord():将字符转成对应的整数 dir():将参数的方法显示出来。 divmod(被除数,除数):返回的是一个元组,元组的第一个为商,第二个为余数 hash():将参数生成一个hash值,这个hash值是固定长度的,而且内容改变hash也改变。可以用来校验是否有人修改文件内容。补充:可以hash的数据类型即不可变数据类型,不可hash的数据类型即可变数据类型。 help():参数是方法名,用来查看方法如何使用。 bin():十进制转二进制。0b开头 hex():十进制转十六进制。0x开头 oct():十进制转八进制。0o开头 isinstance(参数一,参数二):判断参数一是不是参数二的实例。比如:isinstance(1,int) globals():显示系统所有的全局变量 locals():显示本模块内局部变量 pow(参数一,参数二,参数三):参数一的参数二次方,参数三可加可不加,加了表示对前两个计算出来的结果取余 reversed():对参数进行反转 round():四舍五入 sorted():排序,不同类型不可以排序,和max原理是一样的,也可以指定一个方法,然后用key传给sorted,默认是升序 sum() :求和 type():返回类型。 __import__():将模块名的字符串形式放入参数中。会导入这个模块 比如: m = __import__("demo") m.say_hello()
其他内置参数可见:https://docs.python.org/3/library/functions.html?highlight=built#ascii