一.内置函数
1.数学运算类
2.集合类操作
内置函数个别使用示例
1.any 集合中的元素有一个为真的时候为真, 特别的,若为空串返回为False
1 print(any([0,'']))
2 print(any([0,'',1]))
执行结果
1 False
2 True
2.divmod 取商得余数,用于做分页显示功能
1 print(divmod(10,3)) #取商得余数,用于做分页显示
执行结果
1 (3, 1)
3.eval 把字符串中的数据结构给提取出来
1 dic={'name':'alex'} #字典类型转成字符串
2 dic_str=str(dic)
3 print(dic_str)
4
5 d1=eval(dic_str) #eval:把字符串中的数据结构给提取出来
6 print(d1)
执行结果
1 {'name': 'alex'}
2
3 {'name': 'alex'}
4.可hash的数据类型即不可变数据类型,不可hash的数据类型即可变数据类型
1 #hash的作用:去网上下载软件,判断是否被人修改,通过比对hash值,就知道
2 print(hash('12sdfdsaf3123123sdfasdfasdfasdfasdfasdfasdfasdfasfasfdasdf'))
3 print(hash('12sdfdsaf31231asdfasdfsadfsadfasdfasdf23'))
4
5 name='alex'
6 print(hash(name))
7 print(hash(name))
8
9 print('--->before',hash(name))
10 name='sb'
11 print('=-=>after',hash(name))
执行结果
1 1982976672
2 864959982
3 -2006403263
4 -2006403263
5 --->before -2006403263
6 =-=>after 805524431
5.bin、hex、oct 进制转换
1 print(bin(10)) #10进制->2进制
2 print(hex(12)) #10进制->16进制
3 print(oct(12)) #10进制->8进制
执行结果
1 0b1010 #10进制->2进制
2 0xc #10进制->16进制
3 0o14 #10进制->8进制
6.isinstance判断类型
1 print(isinstance(1,int)) #判断是不是int类型
2 print(isinstance('abc',str)) #判断字符串
3 print(isinstance([],list)) #判断列表
4 print(isinstance({},dict)) #判断字典
5 print(isinstance({1,2},set)) #判断集合
执行结果
1 True
2 True
3 True
4 True
5 True
7.max 最大值 和 min最小值
1 l=[1,3,100,-1,2]
2 print(max(l))
3 print(min(l))
执行结果
1 100 #最大值
2 -1 #最小值
max 高级用法
说明:
1、max函数处理的是可迭代对象,相当于一个for循环取出每个元素进行比较
注意:不同类型之间不能进行比较
2、每个元素间进行比较,是从每个元素的第一位置依次比较,如果这一个位置分出大小,后
面的都不需要比较了,直接得出这俩元素的大小。
1 age_dic={'alex_age':18,'wupei_age':20,'zsc_age':100,'lhf_age':30}
2 print(max(age_dic.values())) #取出最大年龄
3 print(max(age_dic)) #默认比较的是字典的key
执行结果
1 100
2 zsc_age
ps: 取出年龄最大的key和values
1 age_dic={'alex_age':18,'wupei_age':20,'zsc_age':100,'lhf_age':30}
2 for item in zip(age_dic.values(),age_dic.keys()): #[(18,'alex_age') (20,'wupeiqi_age') () () ()]
3 print(item)
4
5 #取出年龄最大的key和values
6 print('=======>',list(max(zip(age_dic.values(),age_dic.keys())))) #max和zip联合使用
执行结果
1 (100, 'zsc_age')
2 (30, 'lhf_age')
3 (18, 'alex_age')
4 (20, 'wupei_age')
5
6
7 =======> [100, 'zsc_age'] #取出年龄最大的key和values
ps.
1 l=[
2 (5,'e'),
3 (1,'b'),
4 (3,'a'),
5 (4,'d'),
6 ]
7 l1=['a10','b12','c10',100] #不同类型之间不能进行比较
8 l1=['a10','a2','a10'] #不同类型之间不能进行比较
9 print(list(max(l)))
10
11 print('--->',list(max(l1)))
执行结果
1 [5, 'e']
2 ---> ['a:', '2']
8.zip 将对象逐一配对
PS1
1 print(list(zip(('a','n','c'),(1,2,3))))
2 print(list(zip(('a','n','c'),(1,2,3,4))))
3 print(list(zip(('a','n','c','d'),(1,2,3))))
执行结果
1 [('a', 1), ('n', 2), ('c', 3)]
2 [('a', 1), ('n', 2), ('c', 3)]
3 [('a', 1), ('n', 2), ('c', 3)]
ps2:
1 p={'name':'alex','age':18,'gender':'none'}
2 print(list(zip(p.keys(),p.values())))
3 print(list(p.keys())) #取keys
4 print(list(p.values())) #values
5
6 print(list(zip(['a','b'],'12345'))) #列表,只要是序列就可以打印出来
执行结果
1 [('age', 18), ('name', 'alex'), ('gender', 'none')]
2 ['age', 'name', 'gender']
3 [18, 'alex', 'none']
4 [('a', '1'), ('b', '2')]
PS3:总结
1 l=[1,3,100,-1,2]
2 print(max(l)) #比较出最大值
3
4
5 dic={'age1':18,'age2':10}
6 print(max(dic)) #比较的是key
7
8
9 print(max(dic.values())) #比较的是key,但是不知道是那个key对应的值
10
11
12 print(max(zip(dic.values(),dic.keys()))) #结合zip使用
执行结果
1 100 #比较大小,得出最大值
2
3 age2 #比较的是key
4
5 18 #比较的是key,但是不知道是那个key对应的值
6
7 (18, 'age1') #结合zip拿用
ps:
1 people=[
2 {'name':'alex','age':1000},
3 {'name':'wupei','age':10000},
4 {'name':'yuanhao','age':9000},
5 {'name':'linhaifeng','age':18},
6 ]
7 # max(people,key=lambda dic:dic['age'])
8 print(max(people,key=lambda dic:dic['age'])) #提取年龄中的values,再进行比较
9
10 #上面题分解步骤,先取出ret的值,再给max进行比较
11 people=[
12 {'name':'alex','age':1000},
13 {'name':'wupei','age':10000},
14 {'name':'yuanhao','age':9000},
15 {'name':'linhaifeng','age':18},
16 ]
17
18 ret=[]
19 for item in people:
20 ret.append(item['age'])
21 print(ret)
22 max(ret)
执行结果
1 #提取年龄中的values,再进行比较大小,得出age最大的
2
3{'name': 'wupei', 'age': 10000}
4
5
6 #上面题分解步骤,先取出ret的值,再给max进行比较,得出的值:
7
8 [1000, 10000, 9000, 18]
9.reversed 反转
1 l=[1,2,3,4]
2 print(list(reversed(l)))
3 print(l)
执行结果
1 [4, 3, 2, 1] #反转
2 [1, 2, 3, 4]
10.round 四舍五入
1 print(round(3.5)) #四舍五入
执行结果
1 4
11.slice 切片
1 l='hello'
2 s1=slice(3,5) #切片 取3到5的元素
3 s2=slice(1,4,2) #切片,指定步长为2
4 print(l[3:5])
5
6 print(l[s1]) #切片
7 print(l[s2])
8
9 print(s2.start) #开始
10 print(s2.stop) #结束
11 print(s2.step) 步长
执行结果
1 lo
2
3 lo
4
5 el
6
7 1
8
9 4
10
11 2
12.sorted 排序
ps1:
1 l=[3,2,1,5,7]
2 l1=[3,2,'a',1,5,7]
3 print(sorted(l)) #排序
4 # print(sorted(l1)) #直接运行会报错,因为排序本质就是在比较大小,不同类型之间不可以比较大小
执行结果
1 [1, 2, 3, 5, 7]
ps2:
1 people=[
2 {'name':'alex','age':1000},
3 {'name':'wupei','age':10000},
4 {'name':'yuanhao','age':9000},
5 {'name':'linhaifeng','age':18},
6 ]
7 print(sorted(people,key=lambda dic:dic['age'])) #按年龄进行排序
执行结果
1 [{'age': 18, 'name': 'linhaifeng'}, {'age': 1000, 'name': 'alex'}, {'age': 9000, 'name': 'yuanhao'}, {'age': 10000, 'name': 'wupei'}]
ps3:
1 name_dic={
2 'abyuanhao': 11900,
3 'alex':1200,
4 'wupei':300,
5 }
6 print(sorted(name_dic)) #按key排序
7
8 print(sorted(name_dic,key=lambda key:name_dic[key])) #取出字典的values
9
10 print(sorted(zip(name_dic.values(),name_dic.keys()))) #按价格从低到高排序
执行结果
1 ['abyuanhao', 'alex', 'wupei']
2
3 ['wupei', 'alex', 'abyuanhao']
4
5 [(300, 'wupei'), (1200, 'alex'), (11900, 'abyuanhao')]
3.高阶函数
map()
函数接收两个参数,一个是函数,一个是Iterable
,map
将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator
返回。
举例说明,比如我们有一个函数f(x)=x2,要把这个函数作用在一个list [1, 2, 3, 4, 5, 6, 7, 8, 9]
上,就可以用map()
实现如下:
现在,我们用Python代码实现:
>>> def f(x):
... return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
map()
传入的第一个参数是f
,即函数对象本身。由于结果r
是一个Iterator
,Iterator
是惰性序列,因此通过list()
函数让它把整个序列都计算出来并返回一个list。
你可能会想,不需要map()
函数,写一个循环,也可以计算出结果:
L = []
for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]:
L.append(f(n))
print(L)
的确可以,但是,从上面的循环代码,能一眼看明白“把f(x)作用在list的每一个元素并把结果生成一个新的list”吗?
所以,map()
作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,比如,把这个list所有数字转为字符串:
>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
['1', '2', '3', '4', '5', '6', '7', '8', '9']
只需要一行代码。
再看reduce
的用法。reduce
把一个函数作用在一个序列[x1, x2, x3, ...]
上,这个函数必须接收两个参数,reduce
把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
比方说对一个序列求和,就可以用reduce
实现:
>>> from functools import reduce
>>> def add(x, y):
... return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25
当然求和运算可以直接用Python内建函数sum()
,没必要动用reduce
。
但是如果要把序列[1, 3, 5, 7, 9]
变换成整数13579
,reduce
就可以派上用场:
>>> from functools import reduce
>>> def fn(x, y):
... return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579
这个例子本身没多大用处,但是,如果考虑到字符串str
也是一个序列,对上面的例子稍加改动,配合map()
,我们就可以写出把str
转换为int
的函数:
>>> from functools import reduce
>>> def fn(x, y):
... return x * 10 + y
...
>>> def char2num(s):
... return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
...
>>> reduce(fn, map(char2num, '13579'))
13579
整理成一个str2int
的函数就是:
from functools import reduce
def str2int(s):
def fn(x, y):
return x * 10 + y
def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
return reduce(fn, map(char2num, s))
还可以用lambda函数进一步简化成:
from functools import reduce
def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
def str2int(s):
return reduce(lambda x, y: x * 10 + y, map(char2num, s))
二.匿名函数
当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。
匿名函数没有函数名,只使用一次。
在Python中,对匿名函数提供了有限支持。还是以map()
函数为例,计算f(x)=x2时,除了定义一个f(x)
的函数外,还可以直接传入匿名函数:
>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]
通过对比可以看出,匿名函数lambda x: x * x
实际上就是:
def f(x):
return x * x
关键字lambda
表示匿名函数,冒号前面的x
表示函数参数。
匿名函数有个限制,就是只能有一个表达式,不用写return
,返回值就是该表达式的结果。
用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:
>>> f = lambda x: x * x
>>> f
<function <lambda> at 0x101c6ef28>
>>> f(5)
25
同样,也可以把匿名函数作为返回值返回,比如:
def build(x, y):
return lambda: x * x + y * y
三.递归
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
举个例子,我们来计算阶乘n! = 1 x 2 x 3 x ... x n
,用函数fact(n)
表示,可以看出:
fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n
所以,fact(n)
可以表示为n x fact(n-1)
,只有n=1时需要特殊处理。
于是,fact(n)
用递归的方式写出来就是:
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
上面就是一个递归函数。可以试试:
>>> fact(1)
1
>>> fact(5)
120
>>> fact(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
如果我们计算fact(5)
,可以根据函数定义看到计算过程如下:
===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。可以试试fact(1000)
:
>>> fact(1000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in fact
...
File "<stdin>", line 4, in fact
RuntimeError: maximum recursion depth exceeded in comparison
解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
上面的fact(n)
函数由于return n * fact(n - 1)
引入了乘法表达式,所以就不是尾递归了。要改成尾递归方式,需要多一点代码,主要是要把每一步的乘积传入到递归函数中:
def fact(n):
return fact_iter(n, 1)
def fact_iter(num, product):
if num == 1:
return product
return fact_iter(num - 1, num * product)
可以看到,return fact_iter(num - 1, num * product)
仅返回递归函数本身,num - 1
和num * product
在函数调用前就会被计算,不影响函数调用。
fact(5)
对应的fact_iter(5, 1)
的调用如下:
===> fact_iter(5, 1)
===> fact_iter(4, 5)
===> fact_iter(3, 20)
===> fact_iter(2, 60)
===> fact_iter(1, 120)
===> 120
尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。
遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)
函数改成尾递归方式,也会导致栈溢出。
def age(n):
if n == 5:
return 18
return age(n+1)+2
print(age(1))
l=[1,[2,3,[4,5,[6,7,[8,9,[10,11,[12,13]]]]]]]
def func(l):
for i in l:
if isinstance(i,list):
func(i)
else:
print(i)
func(l)
四.课后作业
1、文件内容如下,标题为:姓名,性别,年纪,薪资
egon male 18 3000
alex male 38 30000
wupeiqi female 28 20000
yuanhao female 28 10000
要求:
从文件中取出每一条记录放入列表中,
列表的每个元素都是{'name':'egon','sex':'male','age':18,'salary':3000}的形式
1 salary_info=[{'name':line.split()[0],'sex':line.split()[1],'age':int(line.split()[2]),'salary':int(line.split()[3])} for line in open('xinxi.txt',encoding='utf-8')]
2 print(salary_info)
[{'name': 'egon', 'sex': 'male', 'age': 18, 'salary': 3000},
{'name': 'alex', 'sex': 'male', 'age': 38, 'salary': 30000},
{'name': 'wupeiqi', 'sex': 'female', 'age': 28, 'salary': 20000},
{'name': 'yuanhao', 'sex': 'female', 'age': 28, 'salary': 10000}]
2、根据1得到的列表,取出薪资最高的人的信息
print([i for i in max(salary_info,key=lambda x:x['salary']).values()])
#执行结果
['alex', 'male', 38, 30000]
3、根据1到的列表,取出最年轻的人的信息
print([i for i in min(salary_info,key=lambda x:x['age']).values()])
#执行结果
['egon', 'male', 18, 3000]
4、根据1得到的列表,将每个人的信息中的名字映射成首字母大写的形式
print(list(map(lambda x:x['name'].capitalize(),salary_info)))
#执行结果
['Egon', 'Alex', 'Wupeiqi', 'Yuanhao']
5、根据1得到的列表,过滤掉名字以a开头的人的信息
print(list(filter(lambda x:not x['name'].startswith('a'),salary_info)))
#执行结果
[{'name': 'egon', 'sex': 'male', 'age': 18, 'salary': 3000},
{'name': 'wupeiqi', 'sex': 'female', 'age': 28, 'salary': 20000},
{'name': 'yuanhao', 'sex': 'female', 'age': 28, 'salary': 10000}]
6、使用递归打印斐波那契数列(前两个数的和得到第三个数) 0 1 1 2 3 5 8...
def fi(n):
if n==0:
return 0
if n==1 or n==2:
return 1
return fi(n-1)+fi(n-2)
print([fi(i) for i in range(20)])