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
可重入函数.py

    # 不可重入函数:

y = 200

def myadd(x):
    return x + y


print(myadd(100))  # 300
y = 300
print(myadd(100))  # 400
不可重入函数.py

二、高阶函数 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
mymap1.py

   练习 :
      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))))
练习1.py

      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.py

示例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
mymap2.py

 练习:
       求 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)
示例:myfilter.py

  练习:
     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)
练习1

     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)
练习2

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']
练习.py

三、递归函数 recursion

   递归是指 函数直接或间接的调用自身

1、递归示例:

   # 函数直接调用自身
    def f():
        f()  # 直接调用自身
    f()
    print("递归完成")

1 # 此示例示意递归 直接调用自身
2 def f():
3     print("从前有座山,山上有座庙,庙里有个老和尚讲故事:")
4     f()  # 直接调用自身
5 
6 print("开始讲故事")
7 f()
8 print("递归完成")
recursion1.py

  # 函数间接调用自身
    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("程序结束")
recursion2.py

   递归求阶乘示例见:

 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
recursion_factorial.py

练习:
   用递归实现求和:
     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
练习.py

四、闭包 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))
closure1.py
 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))  # ...
closure2.py

  练习:
     已知有五位朋友在一起
        第五个人说它比第四个人大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))
get_age.py

练习:

   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))
练习1.py

  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
练习2.py

   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()
练习3.py

posted on 2018-10-12 17:31  破天荒的谎言、谈敷衍  阅读(495)  评论(0)    收藏  举报

导航