码迷,mamicode.com
首页 > 其他好文 > 详细

Day10:内置函数、匿名函数、递归函数

时间:2017-06-20 23:50:56      阅读:291      评论:0      收藏:0      [点我收藏+]

标签:位置   阶乘   reverse   har   font   filter   不可变   max   item   

一.内置函数

技术分享

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()函数接收两个参数,一个是函数,一个是Iterablemap将传入的函数依次作用到序列的每个元素,并把结果作为新的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是一个IteratorIterator是惰性序列,因此通过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]变换成整数13579reduce就可以派上用场:

>>> 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 - 1num * 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)])

 



 

Day10:内置函数、匿名函数、递归函数

标签:位置   阶乘   reverse   har   font   filter   不可变   max   item   

原文地址:http://www.cnblogs.com/Vee-Wang/p/7056161.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!