1.1、列表生成器
问题引入:看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1
方案一:
a = [1,3,4,6,7,7,8,9,11] for index,i in enumerate(a): a[index] +=1 print(a) 原值修改方案二:
>>> a [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> a = map(lambda x:x+1, a) >>> a <map object at 0x101d2c630> >>> for i in a:print(i) ... 3 5 7 9 11方案三:列表生成器
>>> a = [i+1 for i in range(10)] >>> a [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]1.2、为什么要有生成器呢?
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
1.3、生成器如何创建
方法一,直接把列表生成器的【】变成():
>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10)) >>> g <generator object <genexpr> at 0x1022ef630>可以注意到的是,g不再是一个列表生成器,而是一个generator对象了!!!!
方法二,除了改写列表生成器来构造generator对象之外,还可以用函数实现:
只需要把print-->yield
def fib(max): n, a, b = 0, 0, 1 while n < max: print(b) a, b = b, a + b n = n + 1 return 'done' ################################################## >>> fib(10) 1 1 2 3 5 8 13 21 34 55 done #################################################### def fib(max): n,a,b = 0,0,1 while n < max: #print(b) yield b a,b = b,a+b n += 1 return 'done' ################################################### >>> f = fib(6) >>> f <generator object fib at 0x104feaaa0>可以看到,函数实现的功能是一样的,就是把print-->yield之后,fib(6)就变成了一个generator对象了,而不是一个普通函数
1.4、如何使用gengrator呢
如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:
g = (x * x for x in range(10)) >>> next(g) 0 >>> next(g) 1 >>> next(g) 4 >>> next(g) 9 >>> next(g) 16 >>> next(g) 25 >>> next(g)generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误
我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。
>>> g = (x * x for x in range(10)) >>> for n in g: ... print(n) ... 0 1 4 9 16 25 36 49 64 811.5、总结+理解难点
def fib(max): n,a,b = 0,0,1 while n < max: #print(b) yield b a,b = b,a+b n += 1 return 'done' data = fib(10) print(data) print(data.__next__()) print(data.__next__()) print("干点别的事") print(data.__next__()) print(data.__next__()) print(data.__next__()) print(data.__next__()) print(data.__next__()) ###################################### #输出 <generator object fib at 0x101be02b0> 1 1 干点别的事 2 3 5 8 13最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。在上面fib的例子,我们在循环过程中不断调用yield,就会不断中断
凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列(生成器一定是迭代器);
集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
可以使用isinstance()判断一个对象是否是Iterable对象:
>>> from collections import Iterable >>> isinstance([], Iterable) True >>> isinstance({}, Iterable) True >>> isinstance('abc', Iterable) True >>> isinstance((x for x in range(10)), Iterable) True >>> isinstance(100, Iterable) False可以使用isinstance()判断一个对象是否是Iterator对象:
>>> from collections import Iterator >>> isinstance((x for x in range(10)), Iterator) True >>> isinstance([], Iterator) False >>> isinstance({}, Iterator) False >>> isinstance('abc', Iterator)把list、dict、str等Iterable变成Iterator可以使用iter()函数:
>>> isinstance(iter([]), Iterator) True >>> isinstance(iter('abc'), Iterator) True作业需求:
模拟实现一个ATM + 购物商城程序
额度 15000或自定义实现购物商城,买东西加入 购物车,调用信用卡接口结账可以提现,手续费5%每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息支持多账户登录支持账户间转账记录每月日常消费流水提供还款接口ATM记录操作日志 提供管理接口,包括添加账户、用户额度,冻结账户等。。。用户认证用装饰器
转载于:https://www.cnblogs.com/mesunyueru/p/8970949.html
相关资源:数据结构—成绩单生成器