python基础(11)——函数式编程
一、函数式编程
是指用一系列函数解决问题
示列:
求 1 + 2 + 3 + 4 + .... + 100的和
1 # 方法1 2 s = 0 3 for x in range(1,101): 4 s += x 5 print(s) 6 7 # 方法2 8 print(sum(range(1,101)))
函数的可重入性:
当一个函数的输入一定,则输出必然一定的函数称为可重入函数
说明:
可重入函数内一定不会访问除局部变量以外的变量
示例:
# 可重入函数:
def myadd(x, y): return x + y print(myadd(100, 200)) # 300
# 不可重入函数:
y = 200 def myadd(x): return x + y print(myadd(100)) # 300 y = 300 print(myadd(100)) # 400
二、高阶函数 High Order Function
1、 什么是高阶函数:
满足下列条件中的一个的函数即为高阶函数
1. 函数接收一个或多个函数作为参数传入
2. 函数返回一个函数
2、python内置的高阶函数:
map, filter, sorted
1、map函数:
map(func, *iterable) 返回一个可迭代对象,此可迭代对象用函数func对可迭代对象iterable中的每一个元素作为参数计算后得到新的数据
示例1:
1 # map函数示例 2 def power2(x): 3 return x ** 2 4 5 for x in map(power2, range(1, 10)): 6 print(x) # 1 4 9 16 .... 81
练习 :
1. 求: 1**2 + 2**2 + 3**2 + .... + 9**2的和
1 # 方法1 2 def power2(x): 3 # print("power2被调用!, x=", x) 4 return x ** 2 5 s = 0 # 用来保存和 6 for x in map(power2, range(1, 10)): 7 s += x 8 print(s) 9 10 11 # 方法2 12 s = 0 13 for x in map(lambda x: x ** 2, range(1, 10)): 14 s += x 15 print(s) 16 17 18 # 方法3 19 print(sum(map(lambda x: x**2, range(1, 10))))
2. 求: 1**3 + 2**3 + 3**3 + .... + 9**3的和
1 #方法1 2 def mysum2(x): 3 print("mysum1被调用!,x=",x) 4 return x**3 5 s = 0 6 for x in map(mysum2,range(1,10)): 7 s += x 8 print(s) 9 #方法2 10 s=0 11 for x in map(lambda x: x ** 3, range(1,10)): 12 s += x 13 print(s) 14 # 方法3 15 print(sum(map(lambda x: x**3, range(1, 10))))
示例2:
1 # 生成一个可迭代对象,此可迭代对象能够提供: 2 # 1**4, 2**3, 3**2, 4**1 3 def mypow(x, y): 4 return x ** y 5 6 for i in map(mypow, [1, 2, 3, 4], (4, 3, 2, 1)): 7 print(i) 8 9 print('-------------') 10 for i in map(pow, [1, 2, 3, 4], (4, 3, 2, 1)): 11 print(i) 12 13 print("=============") 14 for i in map(pow, 15 [1, 2, 3, 4], 16 (4, 3, 2, 1), 17 range(5, 1000)): 18 print(i) #1%5=1 8%6=2 9%7=2 4%8=4
练习:
求 1**9 + 2**8 + 3**7 + .... + 9**1的和
答案:
print(sum(map(pow, range(1, 10), range(9, 0, -1))))
2、filter 函数:
filter(function, iterable)
作用:
1. 筛选可迭代对象iterable中的数据,返回一个可迭代对象,此可迭代对象只返回iterable中附合条件的数据
2. function将对iterable中提供的每个数据进行求布尔值,如果为True则保留,返回False 则丢弃此数据
1 # 此函数判断x是否为奇数,如果为奇数返回Ture,否则返回False 2 def isodd(x): 3 return x % 2 == 1 4 5 for x in filter(isodd, range(10)): 6 print(x) #1 3 5 7 9 7 8 L = list(filter(isodd, range(10))) 9 print('L =', L)
练习:
1. 将 1 ~ 20的偶数用filter生成可迭代对象后,将可迭代对象生成的数据存于列表中
最终结果:
L = [2, 4, 6, 8, ... 18, 20]
1 def iseven(x): # 判断x是否是偶数,是偶数返回True,... 2 if x % 2 == 0: 3 return True 4 return False 5 6 # L = list(filter(iseven, range(1, 21))) 7 L = list(filter(lambda x: x % 2 == 0, range(1, 21))) 8 print(L)
2. 用filter函数将 1~100之间所有的素数放入到列表L中
print(L) # [2, 3, 5, 7, 11, ....]
1 def isprime(x): 2 if x < 2: 3 return False 4 for i in range(2, x): 5 if x % i == 0: # 一但整数x就一定不是素数 6 return False 7 return True 8 9 L = list(filter(isprime, range(100))) 10 print(L)
3、sorted 函数
作用:
将原可迭代对象的数据进行排序,生成排序后的列表
函数参数格式:
sorted(iterable, key=None, reverse=False)
说明:
iterable 可迭代对象
key 函数是用来提供一个值,这个值将作为排序的依据,如果不给出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 = sroted(L, key=abs) # [0, 1, -2, 3, -4, 5] 按绝对值
L5 = sorted(L, key=abs, reverse=True) # [5, -4, 3, -2, 1, 0]
names = ['Tom', 'Jerry', 'Spike', 'Tyke']
L6 = sorted(names) # ['Jerry', 'Spike', 'Tom', 'Tyke']
L7 = sorted(names, key=len) # ['Tom', 'Tyke', 'Jerry', 'Spike']
练习:
names = ['Tom', 'Jerry', 'Spike', 'Tyke']
排序的依据为字符串的反序
'moT' 'yrreJ' 'ekipS' 'ekyT'
结果: ['Spike', 'Tyke', 'Tom', 'Jerry']
1 names = ['Tom', 'Jerry', 'Spike', 'Tyke'] 2 # 排序的依据为字符串的反序 3 # 'moT' 'yrreJ' 'ekipS' 'ekyT' 4 def k(s): 5 return s[::-1] 6 7 L = sorted(names, key=k) 8 print(L) # ['Spike', 'Tyke', 'Tom', 'Jerry']
三、递归函数 recursion
递归是指 函数直接或间接的调用自身
1、递归示例:
# 函数直接调用自身
def f():
f() # 直接调用自身
f()
print("递归完成")
1 # 此示例示意递归 直接调用自身 2 def f(): 3 print("从前有座山,山上有座庙,庙里有个老和尚讲故事:") 4 f() # 直接调用自身 5 6 print("开始讲故事") 7 f() 8 print("递归完成")
# 函数间接调用自身
def fa():
fb()
def fb():
fa()
fa()
print("递归完成")
2、递归说明:
递归一定要控制递归的层数,当符合某一条件时要终止递归调用
几乎所有的递归都能用while循环来代替
3、递归的优缺点:
优点:
可以把问题简单化,让思路理会为清晰,代码更简洁
缺点:
递归因系统环境影响大,当递归深度太大时,可能会得到不可预知的结果
4、递归调用分为两个阶段:
递推阶段:
从原问题出发,按递归公式递推,从未知到已知,最终达到递归终止条件
回归阶段:
按递归终止条件求出结果,逆向逐步代入递归公式,回归到原问题求解
5、示例:
限制递归层数的示例:
1 # 限制递归层数的示例: 2 def fx(n): 3 print("递归进入第", n, '层') 4 if n == 3: 5 return 6 fx(n + 1) 7 print("递归退出第", n, '层') 8 9 fx(1) # 调用 10 print("程序结束")
递归求阶乘示例见:
1 # 1. 给出一个数n,写一个函数myfac(n)来计算n!(n的阶乘) 2 # n! = 1*2*3*4*....*n 3 # print(myfac(5)) # 120 4 5 def myfac(n): 6 # 用循环来实现 7 s = 1 8 for i in range(1, n + 1): 9 s *= i 10 return s 11 12 # 用递归来实现 13 # 5! = 5 * 4! 14 # 5! = 5 * 4 * 3! 15 # 5! = 5 * 4 * 3 * 2! 16 # 5! = 5 * 4 * 3 * 2 * 1! 17 # 5! = 5 * 4 * 3 * 2 * 1 18 # 5! = 5 * 4 * 3 * 2 19 # 5! = 5 * 4 * 6 20 # 5! = 5 * 24 21 # 5! = 120 22 23 24 def myfac(n): 25 if n == 1: # 知道1! == 1 26 return 1 27 # 如果n不是1,则递推到下一级求解 28 return n * myfac(n - 1) 29 30 31 print(myfac(5)) # 120
练习:
用递归实现求和:
def mysum(n):
# 返回 1 + 2 + 3 + 4 + .... + n的和
...
print(mysum(100)) # 5050
def mysum(n): if n == 1: return 1 return n + mysum(n - 1) print(mysum(100)) # 5050
四、闭包 closure
1、什么是闭包
闭包是指引用了此函数外部变量的函数
如果一个内嵌函数访问了外部嵌套函数的变量,则这个内嵌函数就是闭包
2、闭包必须满足三个条件:
1. 必须有一个内嵌函数
2. 内嵌函数必须引用外部函数中的变量
3. 外部函数返回值必须是内嵌函数
1 # 写一个函数来创建 x的y次方的函数 2 def make_power(y): 3 def fn(x): 4 return x ** y 5 return fn 6 7 pow2 = make_power(2) 8 print('5的方平是:', pow2(5)) 9 10 def pow3(x): 11 return x ** 3 12 13 pow3 = make_power(3) 14 print('6的三次方是:', pow3(6)) 15 print('5的三次方是:', pow3(5)) 16 17 pow10 = make_power(10) 18 print("2的十次方法:", pow10(2))
1 # 用闭包来创建任意的函数 2 # f(x) = ax2 + bx + c 3 def get_fx(a, b, c): 4 def fx(x): 5 return a * x ** 2 + b * x + c 6 return fx 7 8 f123 = get_fx(1, 2, 3) 9 print(f123(20)) 10 print(f123(50)) 11 12 f654 = get_fx(6, 5, 4) 13 print(f654(10)) # ...
练习:
已知有五位朋友在一起
第五个人说它比第四个人大2岁
第四个人说它比第三个人大2岁
第三个人说它比第二个人大2岁
第二个人说它比第一个人大2岁
第一个人说它10岁
编写程序:
1) 算出第5个人几岁
2) 算出第3个人几岁
1 def age(n): # n代表第n个人 2 if n == 1: 3 return 10 4 return age(n - 1) + 2 5 6 7 print(age(5)) 8 print(age(3))
练习:
1. 写程序算出1~20 的阶乘的和
1! + 2! + 3! + 4! + .... + 20!
1 def myfac(n): 2 '''求阶乘''' 3 s = 1 4 for i in range(1, n + 1): 5 s = s * i # s *= i 6 return s 7 8 9 def sum_factorial(n): 10 # 方法2 11 # return sum(map(myfac, range(1, n + 1))) 12 # 方法1 13 s = 0 14 for i in range(1, n + 1): 15 s += myfac(i) # s += n! 16 return s 17 18 print(sum_factorial(20))
2. 已知有列表:
L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20]
1) 写一个函数 print_list(lst) 打印出所有的数字
print_list(L) # 3 5 8 10 13 ....
2) 写一个函数 sum_list(lst) 返回列表中所有数字的和
print(sum_list(L)) # 106
注:
type(x) 函数可以返一个对象的类型
如:
>>> type(20) is int # True
>>> type([3, 5, 8]) is list # True
>>> type(20) is list # False
1 L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20] 2 def print_list(lst): 3 for x in lst: 4 if type(x) is list: # 是列表 5 print_list(x) 6 else: # 是数字 7 print(x) 8 9 print_list(L) # 3 5 8 10 13 .... 10 11 # L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20] 12 def sum_list(lst): 13 s = 0 14 for x in lst: 15 if type(x) is int: 16 s += x 17 elif type(x) is list: 18 print(x) 19 s += sum_list(x) # 求 x绑定的列表的和 20 21 return s 22 23 24 print('和是:', sum_list(L)) # 106
3. 改写之前的学生信息的程序,要求添加四个功能:
| 5) 按学生成绩高-低显示学生信息 |
| 6) 按学生成绩低-高显示学生信息 |
| 7) 按学生年龄高-低显示学生信息 |
| 8) 按学生年龄低-高显示学生信息 |
1 def input_student(): 2 L = [] # 创建一个新的列表,用此列表准备保存学生信息 3 # 录入学生信息 4 while True: 5 n = input("请输入姓名: ") 6 if not n: 7 break 8 a = int(input("请输入年龄: ")) 9 s = int(input('请输入成绩: ')) 10 # 创建一个新的字典,把学生的信息存入字典中 11 d = {} # 每一次都重新创建一个新的字典 12 d['name'] = n 13 d['age'] = a 14 d['score'] = s 15 L.append(d) 16 return L 17 18 def get_chinese_char_count(x): 19 count = 0 # 先假设个数为0 20 for ch in x: 21 # 如果ch为中文字典,则count 做加一操作 22 if ord(ch) > 127: 23 count += 1 24 return count 25 26 27 def output_student(L): 28 print("+---------------+----------+----------+") 29 print("| name | age | score |") 30 print("+---------------+----------+----------+") 31 for d in L: 32 n = d['name'] 33 a = d['age'] 34 s = d['score'] 35 chinese_cnt = get_chinese_char_count(n) 36 print('|%s|%s|%s|' % (n.center(15-chinese_cnt), 37 str(a).center(10), 38 str(s).center(10) 39 ) 40 ) 41 42 # print("| tarena | 20 | 99 |") 43 # print("| name2 | 30 | 88 |") 44 print("+---------------+----------+----------+") 45 46 47 def del_student(L): 48 n = input('请输入要删除的学生的姓名: ') 49 print("正在删除....", n) 50 51 52 def modify_student_score(L): 53 print("正在修改学生成绩....") 54 55 56 def print_info_by_score_desc(L): 57 def get_score(d): # d是字典 58 return d['score'] 59 60 L2 = sorted(L, key=get_score, reverse=True) 61 output_student(L2) 62 63 64 def print_info_by_score_asc(L): 65 def get_score(d): # d是字典 66 return d['score'] 67 68 L2 = sorted(L, key=get_score) 69 output_student(L2) 70 71 def print_info_by_age_desc(L): 72 L2 = sorted(L, key=lambda d: d['age'], reverse=True) 73 output_student(L2) 74 75 76 def print_info_by_age_asc(L): 77 L2 = sorted(L, key=lambda d: d['age']) 78 output_student(L2) 79 80 81 def show_menu(): 82 print("+---------------------------------+") 83 print("| 1) 添加学生信息 |") 84 print("| 2) 显示学生信息 |") 85 print("| 3) 删除学生信息 |") 86 print("| 4) 修改学生成绩 |") 87 print("| 5) 按学生成绩高-低显示学生信息 |") 88 print("| 6) 按学生成绩低-高显示学生信息 |") 89 print("| 7) 按学生年龄高-低显示学生信息 |") 90 print("| 8) 按学生年龄低-高显示学生信息 |") 91 print("| q) 退出 |") 92 print("+---------------------------------+") 93 94 def main(): 95 L = [] 96 while True: 97 show_menu() 98 s = input("请选择: ") 99 if s == 'q': 100 break 101 elif s == '1': 102 L += input_student() 103 elif s == '2': 104 output_student(L) 105 elif s == '3': 106 del_student(L) 107 elif s == '4': 108 modify_student_score(L) 109 elif s == '5': 110 print_info_by_score_desc(L) 111 elif s == '6': 112 print_info_by_score_asc(L) 113 elif s == '7': 114 print_info_by_age_desc(L) 115 elif s == '8': 116 print_info_by_age_asc(L) 117 118 main()
posted on 2018-10-12 17:31 破天荒的谎言、谈敷衍 阅读(495) 评论(0) 收藏 举报
浙公网安备 33010602011771号