复习: 1、迭代器:不需要索引的取值方式 2、生成器:通过特殊的语法自定义的迭代器 3、枚举对象:为可迭代对象创建索引(按照迭代的顺序创建索引) 迭代器对象:装有多个值的容器 1. 可用通过.__next__()进行取值 2. 取一个少一个 3. 通过.__iter__()得到的还是自身 优点:可以不用依赖索引的统一取值方式(可以产生装有无限个元素的容器) 缺点:只能从前往后取,一次只能取一个(不能获取元素个数) 可迭代对象:可以被迭代的对象 可以通过.__iter__()转换为迭代器对象 for 循环迭代器: 1. 自动获取操作对象的迭代器对象 2. 内部一次调用一个.__next__()获取值 3. 取到末尾自动处理异常,结束循环 for v in [1, 2, 3].__iter__(): print(v) 重点: 1. for 的工作原理 2. 有哪些可迭代对象 思考:迭代器对象能不能按索引取值 # 有限的可以考虑一下,无限的免谈 枚举对象: obj = enumerate('abc') print(obj) obbj = list(obj) print(obj[0]) 可以将有限的直接强转为list进行索引取值 for i, v in enumerate('abc'): print(i, v) 生成器: 1. 结构通过函数方式实现 2. 函数内部返回值不是通过return,而是通过yield 3. 生成器(函数)名 + ()不是调用函数,而是得到生成器对象(自定义迭代器对象) 4. 可以通过.__next__()进行取值,取值一次进入到下一个yield def fn(): # 为得到第一个yield结果的逻辑的代码 yield 1 # 为得到第二个yield结果的逻辑的代码 yield 2 # ... yield 3 # ... yield 4 obj = fn() print(obj) # generator object (生成器对象) print(list(obj)) 今日内容: 1. 三元运算符 | 三目运算符 2. 列表元组推导式 | 字典推导式 3. 递归 4. 匿名函数 5. 内置函数 6. 作业与面向过程概念 一、三元运算符就是 if...else... 的简化语法(语法糖) 前提:if 和 else 只有一条语句 # 判断两数之大 a = 10 b = 20 if a > b: print(a) else: print(b) # 上面的代码用三元表达式来写就是: a = 10 b = 20 print(a if a > b else b) 三元运算符不一定要与条件有直接性关系 a = 10 b = 20 print(b if a > b else a) # 取最小值 二、推导式:列表与字典的转换语法糖 列表(元组)推导式 dic = {'a':1, 'b':2, 'c': 3} # => [('a', 1), ('b', 2), ('c', 3)] res = [(k, v) for k, v in dic.items()] print(res) print(tuple(res)) # 将结果的列表tuple一下就可以获得元组了 run==> [('a', 1), ('b', 2), ('c', 3)] (('a', 1), ('b', 2), ('c', 3)) 字典推导式 ls = [('a', 1), ('b', 2), ('c', 3)] # => {'a': 1, 'b': 2, 'c': 3} res = {k:v for k, v in ls} print(res) run==> {'a': 1, 'b': 2, 'c': 3} 案例: range(10) # range可以被推导为列表 range(10) 其实就是一个[1,2,3,4,5,6,7,8,9]的列表 打印显示时是为[1, 10],是python为了节省内存空间的一种显示方式 res_ls = [arg for arg in range(10)] print(res_ls) # 迭代出可解压的单列容器,可以推导出字典 enumerate('abc') # 取出其中的元素与其相对应的索引,一一配对为元组放入列表中 res_dic = {k:v for k,v in enumerate('abc')} print(res_dic) run==> {0: 'a', 1: 'b', 2: 'c'} 三、递归 递归:回溯 与 递推 回溯:询问答案的过程 递推:推出答案的过程 前提:***** 回溯到一个有具体结果的值,便会开始递推 回溯与递推的条件要有规律 递归的本质:函数的自我调用(自己调自己) import sys sys.setrecursionlimit(100) # 手动设置递归深度 print(sys.getrecursionlimit()) # 默认1000 # 直接调用: 直接调自己 def a(): a() # 执行函数a a() # 执行函数a # 间接调用: 调用别人,别人最终调回自己 def b(): c() # 执行函数c def c(): d() # 执行函数d def d(): b() # 执行函数b b() # 执行函数b 递归案例: # 询问第一个人年龄,回溯条件 小两岁,第五个人说出自己的年龄,推导出第一个人年龄 # 条件:下一个人的年龄比这个人年纪大两岁 def age_get(num): if num == 1: return 58 age = age_get(num - 1) - 2 return age print(age_get(11)) # 阶乘 def factorial(num): if num == 1: return 1 factorial_num = factorial(num - 1) * num return factorial_num print(factorial(6)) 四、匿名函数:没有名字的函数 定义语法: lambda 参数列表: 一个返回值表达式 没有函数名,没有函数体,只有一个返回值 关键字: lambda | 参数列表省略() f = lambda x, y: (x +y, x -y) #想要返回多个值就要括号括起来 print(f) print(f(10, 20)) 应用场景: 1. 匿名函数函数地址可以被一个变量接受,该变量就可以作为函数名来使用 2. 结合内置函数来使用:内置函数某些参数需要一个函数地址, 可以复制一个有名函数名,也可以直接赋值匿名函数 # 内置函数max() 可以设置两个参数,后面一个参数需要是一个函数读内存地址 def fn(arg): print(arg) return arg ls = [100, 200, 50, 10] res = max(ls, key=fn) # 函数fn从前面的ls中取值 print('------------------------') print(res) res1 = max(ls, key=lambda ele: ele) # 直接给后面的参数一个匿名函数用来取值 print(res1)