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 
map.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 
 17 
map2.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))))
 28 
1,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 
 22 
filter.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 
 31 
2

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 
recursio.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))  # 120
recursio_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 
 19 
mysum

思考题:
   已知有五位朋友在一起
     第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
  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 
2


  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 
3

闭包的注意事项:
   由于闭包会使得函数中的变量都被保存在内存中,内存消耗比较大,所
   以不能滥用闭包
闭包的应用示例见:
   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 
1

   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 
2

   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 
3
posted @ 2019-01-25 19:58  圣枷  阅读(298)  评论(0编辑  收藏  举报