day10回顾
函数名是变量,它用来绑定"函数"
函数可以作为参数传入另一个函数
函数可以返回另一个函数
函数的嵌套定义
def f1():
def f2():
pass
f2()
四个作用域:
局部作用域
外部嵌套函数作用域
全局作用域
内建作用域
LEGB
global 语句
nonlocal 语句
lambda 表达式
作用:
创建简单的匿名函数
语法:
lambda 形参列表: 表达式
等同于:
def xxxx(形参列表):
return 表达式
eval(字符串, globals=None, locals=None) 函数
exec(字符串, globals=None, locals=None) 函数
day11 笔记:
函数式编程 Functional Programming
函数式编程是指用一系列函数解决问题
好处:
用每一个函数完全细小的功能,一系列函数的任意组合可以完成大问题
函数仅接受输入并产生输出,不包含任何能影响输出的内部状态
函数的可重入性
当一个函数没有访问除局部变量以外的变量,则此函数为可重入函数
说明:
可重入函数输入一定.结果必然一定
示例:
# 可重入函数:
def myadd1(x, y):
return x + y
# 不可重入函数
s = 0
def myadd2(x, y):
global s
s += x + y
return s
高阶函数 High Order Function
什么是高阶函数:
满足下列条件中的一个的函数即为高阶函数
1. 函数接收一个或多个函数作为参数传入
2. 函数返回一个函数
python 内置的高阶函数:
map, filter, sorted
map 函数
参数格式:
map(func, iterable, ...)
参数:
func 对可迭代对象的数据进行处理的函数,函数的参数必须
与可迭代对象的个数相同
iterable, 一个或多个可迭代对象,用来给map提供数据
返回值:
可迭代对象
示例见:
map.py
map2.py
1 # map.py
2
3
4 # 此示例示意map的用法
5 def power2(x):
6 print("power2被调用! x=", x)
7 return x ** 2
8
9 # 生成一个可迭代对象,此可迭代对象可以生成1~9自然数的平方
10 # 1 4 9 16 25 36 .... 81
11
12 for x in map(power2, range(1, 10)):
13 print(x) # 1, 4, 9, 16, 25, ...
14
15 # 求:
16 # 1 + 4 + 9 + 16 + .... + 81的和
17 print(sum(map(power2, range(1, 10))))
18map.py
1 # map2.py
2
3 # 生成一个可迭代对象,此可迭代对象可以生成
4 # 1**4, 2**3, 3**2, 4**1
5 # pow(x, y, z=None) 内建函数
6
7
8 for x in map(pow, [1, 2, 3, 4], [4, 3, 2, 1]):
9 print(x) # 1, 8, 9, 4
10
11 print('-----------')
12 for x in map(pow, [1,2,3,4],
13 [4, 3, 2, 1, 0],
14 range(5, 10)):
15 print(x) # 1, 2, 2, 4
16
17map2.py
练习:
1. 求:
1**2 + 2**2 + 3**2 + .... + 9**2的和
2. 求:
1**3 + 2**3 + 3**3 + .... + 9**3的和
3. 求:
1**9 + 2**8 + 3**7 + .... + 9**1的和
1 # 练习:
2 # 1. 求:
3 # 1**2 + 2**2 + 3**2 + .... + 9**2的和
4 # 2. 求:
5 # 1**3 + 2**3 + 3**3 + .... + 9**3的和
6 # 3. 求:
7 # 1**9 + 2**8 + 3**7 + .... + 9**1的和
8
9
10
11 # 1. 求:
12 # 1**2 + 2**2 + 3**2 + .... + 9**2的和
13 # 方法1
14 # def power2(x):
15 # return x ** 2
16 # print(sum(map(power2, range(1, 10))))
17
18 # 方法2
19 print(sum(map(lambda x: x**2, range(1, 10))))
20
21 # 2. 求:
22 # 1**3 + 2**3 + 3**3 + .... + 9**3的和
23 print(sum(map(lambda x: x**3, range(1, 10))))
24
25 # 3. 求:
26 # 1**9 + 2**8 + 3**7 + .... + 9**1的和
27 print(sum(map(pow, range(1, 10), range(9, 0, -1))))
281,2,3
filter 函数
参数格式:
filter(func, iterable)
参数说明:
func 含有一个形参的数据处理函数,此函数传入的值为iterable
中提供的数据,func将对iterable中的每个元素进行求布尔
值,返回True则保留此数据,返回False则将此数据丢弃
iterable 为提供数据的可迭代对象
返回值:
可迭代对象
作用:
筛选数据
示例见:
filter.py
1 # filter.py
2
3 def is_odd(x):
4 '''此函数判断x是否是奇数,是奇数返回True,否则返回False'''
5 # print(x % 2 == 1)
6 return x % 2 == 1
7
8 # 打印1 ~ 20 的奇数:
9 for x in filter(is_odd, range(20)):
10 print(x)
11
12 print('-------------')
13 for x in filter(lambda x: x % 2 == 1, range(10)):
14 print(x)
15
16 # 生成20以内的全部偶数(不包含20)的列表
17 L = list(filter(lambda x: x % 2 == 0, range(20)))
18 print(L)
19 L2 = [x for x in filter(lambda x: x % 2 == 0, range(20))]
20 print("L2=", L2)
21
22filter.py
练习:
1. 用filter 生成能够提供偶数可迭代对象,生成1 ~ 20 的偶数,
将这些偶数存于列表中,再打印这个列表(不包含20)
2. 用filter函数,将1~100之间所有的素数prime 放入到列表中,
再打印这个列表
1 # 1. 用filter 生成能够提供偶数可迭代对象,生成1 ~ 20 的偶数,
2 # 将这些偶数存于列表中,再打印这个列表(不包含20)
3
4 flt = filter(lambda x: x % 2 == 0, range(1, 20))
5 L = list(flt)
6 print(L) # [2, 4, 6, 8 ...]
7
8 L2 = [x for x in flt]
9 print("L2=", L2) # 空列表1~20
1 # 1. 用filter 生成能够提供偶数可迭代对象,生成1 ~ 20 的偶数,
2 # 将这些偶数存于列表中,再打印这个列表(不包含20)
3
4 L = list(filter(lambda x: x % 2 == 0, range(1, 20)))
5 print(L) # [2, 4, 6, 8 ...]
6
7 L2 = [x for x in filter(lambda x: x % 2 == 0, range(1, 20))]
8 print("L2=", L2) # 空列表1~100
1 # 2. 用filter函数,将1~100之间所有的素数prime 放入到列表中,
2 # 再打印这个列表
3
4
5 # 写一个函数,is_prime(x), 判断如果x是素数返回True, 否则返回False
6 def is_prime(x):
7 if x < 2: # 小于2的数没有素数
8 return False
9 # 大于等于2的数.如果能被2, 3, 4, ... x -1 整数,就不是素数
10 for i in range(2, x):
11 if x % i == 0:
12 return False # x不是素数
13 # 走到此处,则x一定为素数
14 return True
15
16 # 方法1
17 L1 = list(filter(is_prime, range(100)))
18 print("L1=", L1)
19
20 L2 = [x for x in filter(is_prime, range(100))]
21 print("L2=", L2)
22
23 L3 = [x for x in range(100) if is_prime(x)]
24 print("L3=", L3)
25
26
27
28
29
30
312
sorted 函数:
作用:
将原可迭代对象的数据进行排序,生成排序后的列表
格式:
sorted(iterable, key=None, reverse=False)
参数说明:
iterable 用来提供数据的可迭代对象
key 函数是用来提供一个值,这个值将作为排序的依据
reverse 标志用来设置是否为降序排序(默认为升序排序)
示例:
L = [5, -2, -4, 0, 3, 1]
L2 = sorted(L) # [-4, -2, 0, 1, 3, 5]
L3 = sorted(L, reverse=True) #[5, 3, 1, 0, -2, -4]
L4 = sorted(L, key=abs) # L4=[0, 1, -2, 3, -4, 5]
names = ['Tom', 'Jerry', 'Spike', 'Tyke']
sorted(names) # ['Jerry', 'Spike', 'Tom', 'Tyke']
sorted(names, key=len)
练习:
names = ['Tom', 'Jerry', 'Spike', 'Tyke']
排序的依据为字符串的反序:
'moT' 'yrreJ' 'skipS' 'ekyT'
排序的结果为:
['Spike', 'Tyke', 'Tom', 'Jerry']
请问如何用sorted进行排序
1 # 练习:
2 # names = ['Tom', 'Jerry', 'Spike', 'Tyke']
3 # 排序的依据为字符串的反序:
4 # 'moT' 'yrreJ' 'skipS' 'ekyT'
5 # 排序的结果为:
6 # ['Spike', 'Tyke', 'Tom', 'Jerry']
7 # 请问如何用sorted进行排序
8
9
10
11 def reverse_str(s):
12 '''s绑定需要排序的可迭代对象提供的元素'''
13 r = s[::-1] # 把转原字符串
14 print("要排序的元素:", s, '排序的依据是:', r)
15 return r
16
17 names = ['Tom', 'Jerry', 'Spike', 'Tyke']
18
19 L = sorted(names, key=reverse_str)
20
21 print(L) # ['Spike', 'Tyke', 'Tom', 'Jerry']
22
23
24
25
26
27
28
递归函数 recursion Function
故事:
从前有座山,山上有座庙,庙里有个老和尚讲故事:
从前有座山,山上有座庙,庙里有个老和尚讲故事:
从前有座山,山上有座庙,庙里有个老和尚讲故事:
1 # recursion_story.py
2
3 def story():
4 print("从前有座山, 山上有座庙,庙里有个老和尚讲故事:")
5 story()
6
7 story()
8
递归函数:
函数直接或间接的调用自身
示例:
# 函数直接调用自身
def f():
f() # 调用自己
f()
# 函数间接调用自身
def fa():
fb() # 调用另一个函数fb
def fb():
fa() # 调用fa
fa()
递归说明:
递归一定要控制递归的层数,当符合某一条件时要终止递归调用
几乎所有的递归都能用while循环来代替
递归的优缺点:
优点:
递归可以把问题简单化,让思路更为清晰,代码更为简洁
缺点:
递归因系统环境影响大,当递归深度太大时,可能会得到不可预知
的结果
递归的两个阶段:
递推阶段: 从原问题出发,按递归公式递推,从未知到已知,最终达到
递归的终止条件
回归阶段: 按递归终止条件求出结果,逆向逐步代入递归公式,回归
原问题求解
递归函数的实现方法:
先假设函数已经实现了原功能,再编写函数
示例见:
recursion.py
# 递归求阶乘示例见:
recursion_factorial.py
1 # recursion.py
2
3 def fx(n):
4 print('递归进入第', n, '层')
5 if n == 3:
6 return
7 fx(n + 1)
8 print('递归退出第', n, '层')
9
10 fx(1)
11 print("程序退出")
12recursio.py
1 # recursion_factorial.py
2 # 1 (如果n为0)
3 # /
4 # n!
5 # \ n * (n-1)! (如果n不为零时)
6
7 def myfac(n):
8 if n == 0: # 0! 为 1
9 return 1
10 else:
11 return n * myfac(n-1) # n! = n * (n-1)!
12
13 print(myfac(5)) # 120recursio_factorial.py
练习:
写一个递归求和函数:
def mysum(n):
...
此函数求 1 + 2 + 3 + 4 + ..... + n 的和
print(mysum(100)) # 5050
1 # 练习:
2 # 写一个递归求和函数:
3 # def mysum(n):
4 # ...
5 # 此函数求 1 + 2 + 3 + 4 + ..... + n 的和
6
7 # print(mysum(100)) # 5050
8
9
10 def mysum(n):
11 if n == 1:
12 return 1
13 # 其它情况
14 return n + mysum(n-1)
15
16
17 print(mysum(100)) # 5050
18
19mysum
思考题:
已知有五位朋友在一起
第5个人说他比第4个人大2岁
第4个人说他比第3个人大2岁
第3个人说他比第2个人大2岁
第2个人说他比第1个人大2岁
第1个人说他10岁
编写程序求:
1) 算出第五个人几岁
2) 算出第三个人几岁
1 # 思考题:
2 # 已知有五位朋友在一起
3 # 第5个人说他比第4个人大2岁
4 # 第4个人说他比第3个人大2岁
5 # 第3个人说他比第2个人大2岁
6 # 第2个人说他比第1个人大2岁
7 # 第1个人说他10岁
8 # 编写程序求:
9 # 1) 算出第五个人几岁
10 # 2) 算出第三个人几岁
11
12 def get_age(n):
13 if n == 1:
14 return 10
15 return get_age(n - 1) + 2
16
17 print('第五个人', get_age(5), '岁')
18 print('第三个人', get_age(3), '岁')
19
20
21
闭包 closure
什么是闭包?
闭包是指引用了此函数外部嵌套函数作用域的变量的函数
闭包必须满足三个条件:
1. 必须有一个内嵌函数
2. 内嵌函数必须引用外部函数中的变量
3. 外部函数返回值必须是内嵌函数
全局变量和局部变量的区别:
全局变量:
一直存在,谁都可以访问和修改
局部变量:
只是在函数调用时存在,只能在函数内部进行访问和修改
示例见:
closure.py
closure2.py
closure3.py
1 # closure.py
2
3 # 用全局变量保存压岁钱
4
5 money = 1000 # 爸爸给函数的压岁钱
6
7 def child_buy(obj, m):
8 global money
9 if money > m:
10 money -= m
11 print('买', obj, '花了', m, '元,剩余',
12 money,'元')
13 else:
14 print("买", obj, '失败')
15
16 child_buy("变形金刚", 200)
17 money = 0 # 钱被偷走了
18 child_buy('漫画三国', 100)
19 child_buy('手机', 1300)
20
21
22
23
24
25
261
1 # closure.py
2
3 # 用局部变量保存压岁钱(不附合逻辑)
4
5 def child_buy(obj, m):
6 money = 1000 # 爸爸给函数的压岁钱
7 if money > m:
8 money -= m
9 print('买', obj, '花了', m, '元,剩余',
10 money,'元')
11 else:
12 print("买", obj, '失败')
13
14 child_buy("变形金刚", 200)
15 child_buy('漫画三国', 100)
16 child_buy('手机', 1300)
17
18
19
20
21
22
232
1 # closure.py
2
3 # 用外部嵌套函数内的变量保存压岁钱
4
5 def give_yasuiqian(money):
6 def child_buy(obj, m):
7 nonlocal money
8 if money > m:
9 money -= m
10 print('买', obj, '花了', m, '元,剩余',
11 money,'元')
12 else:
13 print("买", obj, '失败')
14 return child_buy # 返回内嵌函数的引用关系
15
16 cb = give_yasuiqian(1000) # 给压岁钱1000
17
18 cb("变形金刚", 200)
19 cb('漫画三国', 100)
20 cb('手机', 1300)
21
22
23
24
25
26
273
闭包的注意事项:
由于闭包会使得函数中的变量都被保存在内存中,内存消耗比较大,所
以不能滥用闭包
闭包的应用示例见:
closure_make_power.py
1 # closure_make_power.py
2
3 # 此示例示意闭包的应用
4
5 # 写一个求x的平方的函数
6 # def pow2(x):
7 # return x**2
8 # 写一个求x的立方的函数
9 # def pow3(x):
10 # return x**3
11
12 # 写一个求x的102次方的函数
13 # def pow102(x):
14 # return x**102
15
16 # 写一个求x的150次方的函数
17 # def pow150(x):
18 # return x**150
19
20 # 用闭包实现上述功能
21 def make_power(y):
22 def fn(x):
23 return x ** y # y为外部嵌套函数的变量
24 return fn
25
26 pow2 = make_power(2)
27 print('5的平方是:', pow2(5))
28 print('6的平方是:', pow2(6))
29 pow3 = make_power(3)
30 print('7的立方是:', pow3(7))
31 # ....
32 pow150 = make_power(150)
33 print(pow150(2))
34
35
小结:
函数式编程:
高阶函数:
map, filter, sorted
递归函数
闭包
练习:
1. 写程序算出1~20的阶乘的和,即:
1!+2!+3!+4!+......+19!+20!
1 # 1. 写程序算出1~20的阶乘的和,即:
2 # 1!+2!+3!+4!+......+19!+20!
3
4 def myfac(x):
5 if x == 0:
6 return 1
7 return x * myfac(x-1)
8
9 # 方法1
10 # s = 0
11 # for x in range(1, 21):
12 # s += myfac(x)
13 # print('和是:', s)
14
15 # 方法2
16 print("和是:", sum(map(myfac, range(1, 21))))
17
181
2. 已知有列表:
L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20]
1) 写一个函数print_list(lst) 打印出所有的数字
如:
print_list(L) # 打印 3 5 8 10 13 14 ....
(不要求打印在一行内)
2) 写一个函数 sum_list(lst) 返回这个列表中所有数字的和
如:
print(sum_list(L)) # 打印 106
注:
type(x) 可以返回一个变量的类型
如:
>>> type(20) is int # True
>>> type([1, 2, 3]) is list # True
1 # 2. 已知有列表:
2 # L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20]
3 # 1) 写一个函数print_list(lst) 打印出所有的数字
4 # 如:
5 # print_list(L) # 打印 3 5 8 10 13 14 ....
6 # (不要求打印在一行内)
7 # 2) 写一个函数 sum_list(lst) 返回这个列表中所有数字的和
8 # 如:
9 # print(sum_list(L)) # 打印 106
10 # 注:
11 # type(x) 可以返回一个变量的类型
12 # 如:
13 # >>> type(20) is int # True
14 # >>> type([1, 2, 3]) is list # True
15
16
17
18 L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20]
19
20 def print_list(lst, newline=False):
21 for x in lst:
22 if type(x) is list: # 如果是列表,则按相同规则打印列表
23 print_list(x)
24 else: # 如果是数字则直接打印
25 print(x, end=' ')
26 if newline:
27 print() # 换行
28
29 print_list(L, True) # 3 5 8 10 13 14 ....
30
31
32 def sum_list(lst):
33 s = 0
34 for x in lst:
35 if type(x) is list:
36 s += sum_list(x)
37 else:
38 s += x
39 return s
40
41 print(sum_list(L)) # 106
42
432
3. 修改之前学生信息的程序
要求添加四个功能
| 5) 按学生成绩高-低显示学生信息 |
| 6) 按学生成绩低-高显示学生信息 |
| 7) 按学生年龄高-低显示学生信息 |
| 8) 按学生年龄低-高显示学生信息 |
1
2 # 3. 改写之前的学生信息管理程序:
3 # 用两个函数来封装功能的代码块
4 # 函数1: input_student() # 返回学生信息字典的列表
5 # 函数2: output_student(L) # 打印学生信息的表格
6
7 def input_student():
8 L = [] # 创建一个列表,准备存放学生数据的字典
9 while True:
10 n = input("请输入姓名:")
11 if not n: # 如果用户输入空字符串就结束输入
12 break
13 a = int(input("请输入年龄:"))
14 s = int(input("请输入成绩:"))
15 d = {} # 一定要每次都创建一个新的字典
16 d['name'] = n
17 d['age'] = a
18 d['score'] = s
19 L.append(d) # 把d加入列表中L
20 return L
21
22 def output_student(L):
23 print("+---------------+----------+----------+")
24 print("| 姓名 | 年龄 | 成绩 |")
25 print("+---------------+----------+----------+")
26 for d in L:
27 name = d['name']
28 age = str(d['age']) # 转为字符串
29 score = str(d['score']) # 转为字符串
30 print("|%s|%s|%s|" % (name.center(15),
31 age.center(10),
32 score.center(10)))
33 print("+---------------+----------+----------+")
34
35 def delete_student(L):
36 name = input("请输入要删除学生的姓名:")
37 i = 0 # i 代表列表的索引
38 while i < len(L):
39 d = L[i] # d绑定字典
40 if d['name'] == name:
41 del L[i]
42 print("删除", name, "成功!")
43 break
44 else:
45 print("删除失败!")
46
47 def modify_student_score(L):
48 pass
49
50
51 def output_by_score_desc(L):
52 def get_score(d):
53 return d['score']
54 L2 = sorted(L, key=get_score, reverse=True)
55 output_student(L2)
56
57 def output_by_score_asc(L):
58 L2 = sorted(L, key=lambda d:d['score'])
59 output_student(L2)
60
61 def output_by_age_desc(L):
62 L2 = sorted(L, key=lambda d:d['age'], reverse=True)
63 output_student(L2)
64
65 def output_by_age_asc(L):
66 L2 = sorted(L, key=lambda d:d['age'])
67 output_student(L2)
68
69
70
71
72
73 def show_menu():
74 '''显示菜单'''
75 print("+--------------------------------+")
76 print("| 1) 添加学生信息 |")
77 print("| 2) 显示学生信息 |")
78 print("| 3) 删除学生信息 |")
79 print("| 4) 修改学生成绩 |")
80 print("| 5) 按学生成绩高-低显示学生信息 |")
81 print("| 6) 按学生成绩低-高显示学生信息 |")
82 print("| 7) 按学生年龄高-低显示学生信息 |")
83 print("| 8) 按学生年龄低-高显示学生信息 |")
84 print("| q) 退出 |")
85 print("+--------------------------------+")
86
87
88 def main():
89 infos = [] # 此列表用于保存学生数据
90 while True:
91 show_menu()
92 s = input("请选择:")
93 if s == '1':
94 infos += input_student()
95 elif s == '2':
96 output_student(infos)
97 elif s == '3':
98 delete_student(infos)
99 elif s == '4':
100 modify_student_score(infos)
101 elif s == '5':
102 output_by_score_desc(infos)
103 elif s == '6':
104 output_by_score_asc(infos)
105 elif s == '7':
106 output_by_age_desc(infos)
107 elif s == '8':
108 output_by_age_asc(infos)
109 elif s == 'q':
110 break
111
112 main()
1133