PYTHON1.day11(n)
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)))) 18
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 17
练习:
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)))) 28
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 22
练习:
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 # 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 # 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 31
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("程序退出") 12
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)) # 120
练习:
写一个递归求和函数:
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 19
思考题:
已知有五位朋友在一起
第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 26
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 23
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 27
闭包的注意事项:
由于闭包会使得函数中的变量都被保存在内存中,内存消耗比较大,所
以不能滥用闭包
闭包的应用示例见:
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 18
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 43
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() 113