1.迭代器

1.1 什么是可迭代对象(Iterable)?

定义:可以直接作用于for循环的对象统称为可迭代对象,即Iterable。

可迭代对象包括:

1.集合数据类型:如list、tuple、dict、set、str等;

2.生成器类型:包括生成器和带yield的生成器函数。

1.2 什么又是迭代器(Iterator)?

定义:可以被next()或__next__()函数调用并不断返回下一个值(直到没有数据时抛出StopIteration错误)的对象称为迭代器,即Iterator。

迭代器的生成: __iter__()生成迭代对象时调用

注意:可迭代对象和迭代器不是一个概念,不要混淆。

使用内置函数isinstance和collections测试:

1 >>> importcollections2 >>> print(isinstance([], collections.Iterable)) #判断列表是不是可迭代的

3 True4 >>> print(isinstance([], collections.Iterator)) #判断列表是不是迭代器

5 False6 >>>

7 >>> print(isinstance((), collections.Iterable)) #判断元组是不是可迭代的

8 True9 >>> print(isinstance((), collections.Iterator)) #判断元组是不是迭代器

10 False11 >>>

12 >>> print(isinstance({}, collections.Iterable)) #判断字典是不是可迭代的

13 True14 >>> print(isinstance({}, collections.Iterator)) #判断元组是不是迭代器

15 False16 >>>

迭代器对象&迭代器测试

以上表明,列表,字典,元组,等都是可迭代的,但都不是迭代器。

迭代器例子:

1 #因为列表不是迭代器,所以没有__next__方法

2 >>> a = [1,2,3,4]3 >>> a.__next__()4 Traceback (most recent call last):5 File "", line 1, in

6 AttributeError: 'list' object has no attribute '__next__'

7

8 #用__iter__()生成迭代器,迭代器可以被__next__调用,每次返回一个值,直到没有数据时抛出StopIteration错误

9 >>> a = [1,2,3,4]10 >>> b = a.__iter__()11 >>> print(type(b))12

13 >>> b.__next__()14 1

15 >>> b.__next__()16 2

17 >>> b.__next__()18 3

19 >>> b.__next__()20 4

21 >>> b.__next__()22 Traceback (most recent call last):23 File "", line 1, in

24 StopIteration25 >>>

迭代器示例

2.生成器

2.1 什么是生成器?

生成器就是迭代器,可以理解为一种数据类型,这种类型自动实现了迭代器协议.(其他的数据类型需要调用自己内置的__iter__方法)。

优点:

效率高,相当于边生产边出售

节省内存空间,按需构建,不是一次性构建

保留函数运行的状态。不是从头运行,是从上一次的状态执行

2.2 生成器在python中的表现形式

生成器表达式:类似于列表推导,但是,生成器按需返回结果的一个对象,而不是一次构建一个结果列表

生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行

示例:

1 #普通函数

2 >>> deftest():3 ... return 1

4 ... return 2

5 ... return 3

6 ...7 >>> g =test()8 >>> print(g) #遇到一个return就停止

9 1

10 >>> print(g) #遇到一个return就停止

11 1

12 >>>

13 >>> print(g.__next__()) #没有__next__()方法

14 Traceback (most recent call last):15 File "", line 1, in

16 AttributeError: 'int' object has no attribute '__next__'

17

18

19 #生成器函数

20 >>> deftest():21 ... yield 1

22 ... yield 2

23 ... yield 3 #和return不同的是可以返回多次

24 ...25 >>> g =test()26 >>>

27 >>> print(g.__next__()) #生成器自动实现了迭成器,所以会有__next__()方法。

28 1

29 >>> print(g.__next__()) #第二次运行保存上一次运行的结果,就是上面说的保存状态。

30 2

31 >>> print(g.__next__())32 3

33 >>> print(g.__next__()) #和迭代器一样,取完了就报StopIteration错。

34 Traceback (most recent call last):35 File "", line 1, in

36 StopIteration37 >>>

38

39 生成器函数示例

生成器函数示例

1 #比如我们要生成一个100万条数据的列表

2 #我们会这样生成

3 li =[]

4 for i in range(1000000):

5 li.append(i)

6 print(li) #这样有个缺点,占用内存较大

7 >>> li = (x for x in range(1000000)) #这就是生成器表达式,和上面唯一不同的是,取一个,给一个,不占用空间。

8 >>> li.__next__()

9 0

10 >>> li.__next__()

11 1

12 >>> li.__next__()

13 2

14 >>> li.__next__()

15 3

16 >>>

生成器表达式示例

2.4 生成器send的用法***

send主要是用于外部与生成器对象的交互,send的参数是指(上一次被挂起的yield语句的返回值)***

1 #*** yield 相当于return ,return是控制函数的返回值的

2 #x=yield的另外一个特性,接受send传过来的值,赋值给x

3

4 deftest():5 print('one')6 first = yield 1

7 print('two', first)8 yield 2

9 print('three')10 yield 3

11 res =test()12

13 #第一次调用

14 print(res.__next__())15 #结果(本次结果one是正常打印,None相当于没有返回值)

16 one17 None18

19 #第二种调用send(本次结果one是正常打印,None是函数没有返回值,two 是正常打印,"我是first"发送给了first,也就是第一次返回的值,2是正常打印)

20 print(res.__next__())21 print(res.send('我是first')) #这里的'我是first'就是上一次被挂起的yield语句的返回值。

22 #结果

23 one24 None25 two 我是first26 2

send示例

2.5 生产者消费者模型

这里学习下生产者消费者模型,以简单介绍下生成器的好处及原理。巩固下send的知识。

首先假设,路边拔丝蛋糕的买卖(两种方法)

1.第一种实现方法,做好了100盒准备卖,用100秒做好100盒蛋糕,然后一盒一盒的卖,来买蛋糕的人只能等做好100盒才能买。所有人都等着。

1 #!/usr/bin/env python

2 #-*- coding: utf-8 -*-

3 importtime4 defshengchan():5 dangao =[]6 for i in range(100):7 time.sleep(1)8 dangao.append('第%s盒蛋糕' %i)9 returndangao10

11 defmai(res):12 for index,dg inenumerate(res):13 time.sleep(1)14 print('第%s个人,买个%s' %(index,dg))15

16 result =shengchan()17 mai(result)18

19 结果:20 第0个人,买个第0盒蛋糕21 第1个人,买个第1盒蛋糕22 第2个人,买个第2盒蛋糕23 第3个人,买个第3盒蛋糕24 第4个人,买个第4盒蛋糕25 第5个人,买个第5盒蛋糕26 第6个人,买个第6盒蛋糕27 第7个人,买个第7盒蛋糕28 第8个人,买个第8盒蛋糕29 第9个人,买个第9盒蛋糕30 第10个人,买个第10盒蛋糕31 ....32 第99个人,买个第99盒蛋糕

买蛋糕方法1

2.第二种实现方法,做一盒卖一盒,用1秒做一盒蛋糕被人买走了,又做了一盒又被人买走了,所有买蛋糕的人只等一秒就开心的买走了想要的蛋糕。

1 #!/usr/bin/env python

2 #-*- coding: utf-8 -*-

3 importtime4 defmai(name):5 print('我是[%s],我要买一盒拔丝蛋糕' %name)6 whileTrue:7 dangao=yield

8 time.sleep(1)9 print('%s 买走了[%s]一盒' %(name,dangao))10

11

12 defshengchan():13 c1 = mai('zhangsan')14 c2 = mai('lisi')15 c3 = mai('wangwu')16 c4 = mai('zhaoliu')17 c1.__next__()18 c2.__next__()19 c3.__next__()20 c4.__next__()21 for i in range(100):22 time.sleep(1)23 c1.send('拔丝蛋糕')24 c2.send('拔丝蛋糕')25 c3.send('拔丝蛋糕')26 c4.send('拔丝蛋糕')27 shengchan()28

29 结果:30 我是[zhangsan],我要买一盒拔丝蛋糕31 我是[lisi],我要买一盒拔丝蛋糕32 我是[wangwu],我要买一盒拔丝蛋糕33 我是[zhaoliu],我要买一盒拔丝蛋糕34 zhangsan 买走了拔丝[蛋糕]一盒35 lisi 买走了拔丝[蛋糕]一盒36 wangwu 买走了拔丝[蛋糕]一盒37 zhaoliu 买走了拔丝[蛋糕]一盒38 zhangsan 买走了拔丝[蛋糕]一盒39 lisi 买走了拔丝[蛋糕]一盒40 wangwu 买走了拔丝[蛋糕]一盒41 zhaoliu 买走了拔丝[蛋糕]一盒

买蛋糕方法2

总结:第二种方法要比第一种方法的效率高,这就是生成器的好处。边做边买。

2.6 列表解析&三元表达式简介

2.6.1 三元表达式

1 #基本判断

2 >>> x=1

3 >>> y=2

4 >>> if x >y:5 ... print(x)6 ... else:7 ... print(y)8 ...9 2

10 >>>

11

12 #三元表达式判断

13 >>> x=1

14 >>> y=2

15 >>> res= print(x) if x > y else print(y)16 2

17 >>>

18

19 #函数返回

20 >>> defmax_xy(x, y):21 ... if x >y:22 ... returnx23 ... else:24 ... returny25 ...26 >>> max_xy(1,2)27 2

28 >>>

29 #三元表达式返回

30 >>> defmax_xy(x, y):31 ... return x if x > y elsey32 ...33 >>> max_xy(1,2)34 2

35 >>>

示例

2.6.2 列表解析

1 #普通方式

2

3 >>> a='hello'

4 >>> l=[]5 >>> for i ina:6 ... res=i.upper()7 ... l.append(res)8 ...9 >>> print(l)10 ['H', 'E', 'L', 'L', 'O']11 >>>

12

13 #列表解析方式

14

15 >>> a='hello'

16 >>> l=[i.upper() for i ina]17 >>> print(l)18 ['H', 'E', 'L', 'L', 'O']19 >>>

20

21 #普通方式

22

23 >>> l=[1,2,3,4,5]24 >>> l_new=[]25 >>> for i inl:26 ... if i > 3:27 ... l_new.append(i)28 ...29 >>>

30 >>> print(l_new)31 [4, 5]32 >>>

33

34 #列表解析方式

35 >>> l=[1,2,3,4,5]36 >>> res=[i for i in l if i > 3]37 >>> print(res)38 [4, 5]39 >>>

40

41 #普通方式

42

43 >>> l=[]44 >>> for i in range(10):45 ... l.append(i)46 ...47 >>> print(l)48 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]49 >>>

50

51 #列表解析方式

52

53 >>> res=[i for i in range(1,10)]54 >>> print(res)55 [1, 2, 3, 4, 5, 6, 7, 8, 9]56 >>>

57

58 #普通方式

59

60 >>> ret =[]61 >>> for x in range(5):62 ... if x % 2 ==0:63 ... for y in range(5):64 ... if y % 2 ==1:65 ... ret.append((x,y))66 ...67 >>> print(ret)68 [(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]69 print(ret)70

71 #列表解析方式

72 >>> ret = [(x,y) for x in range(5) if x % 2==0 for y in range(5) if y % 2 ==1]73 >>> print(ret)74 [(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]75 >>>

示例

3.装饰器

3.1 什么是装饰器

借鉴了知乎上大神形象的比喻,内裤可以用来遮羞,但是到了冬天它没法为我们防风御寒,聪明的人们发明了长裤,有了长裤后宝宝再也不冷了,装饰器就像我们这里说的长裤,在不影响内裤作用的前提下,给我们的身子提供了保暖的功效。^_^.....^_^

定义:装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

遵循以下两个原则:

1.不能修改被修饰函数的源代码

2.不能修改被修饰函数的调用方式

装饰器储备知识:装饰器=高阶函数+函数嵌套+闭包(缺一不可)

3.2 装饰器的好处

比如要实现计算一个函数的运行时间,示例。

原始函数

1 importtime2 defcale(n):3 res =04 for i inn:5 time.sleep(1)6 res+=i7 returnres8

9 print(cale(range(10)))

计算函数的运行时间(普通方式)

1 importtime2 defcale(n):3 start_time =time.time()4 res =05 for i inn:6 time.sleep(1)7 res+=i8 stop_time =time.time()9 print('函数的运行时间是%s' %(stop_time-start_time))10 returnres11 print(cale(range(10)))

这里我们可以实现,在函数之中加了个计算时间的逻辑,如果需求是要计算所有函数的运行时间,那么就显得笨重。这时候就用到装饰器了。

计算函数的运行时间(装饰器方式)

#装饰器

importtimedef zhuangshi(func): #高阶函数,参数是一个函数

def wapper(*args,**kwargs): #函数之内定义函数,是函数的嵌套

start_time = time.time() #闭包:在一个作用域里放入定义变量,相当于打了一个包

res = func(*args,**kwargs)

stop_time= time.time() #闭包:在一个作用域里放入定义变量,相当于打了一个包

print('函数的运行时间是%s' % (stop_time -start_time))returnresreturn wapper #高阶函数,返回值是一个函数

@zhuangshi#@zhuangshi是装饰器的用法,要装饰哪个函数就在函数前加“@装饰器名(装饰器函数名)”等同于cale=zhuangshi(cale)

defcale(n):

res=0for i inn:

time.sleep(1)

res+=ireturnresprint(cale(range(10))) #符合装饰器的原则,调用方式不变

#结论=======>装饰器=高阶函数+函数嵌套+闭包

这样就实现了在任何函数前面加@zhuangshi,就可以计算函数的运行时间了。

3.3 带参数的装饰器

无参数装饰器(以登录京东、访问家目录、访问购物车、为例的装饰器)

1 #!/usr/bin/env python

2 #-*- coding: utf-8 -*-

3

4 #用户列表

5 user_list =[6 {'name':'zhangsan','passwd':'123'},7 {'name':'lisi','passwd':'456'},8 {'name':'wangwu','passwd':'789'},9 ]10 #全局变量一改,其他子程序都会改,用来跟踪用户的登录状态

11 user_dic={'username':None,'login':False}12

13 #无参数装饰器

14 defauth_func(func):15 def wapper(*args, **kwargs):16 if user_dic['username'] and user_dic['login']: #这里判断状态

17 res = func(*args, **kwargs)18 returnres19 username = input('username:').strip()20 passwod = input('password:').strip()21 for userdic inuser_list:22 if username == userdic['name'] and passwod == userdic['passwd']:23 user_dic['username'] =username24 user_dic['login'] =True25 res = func(*args, **kwargs)26 returnres27 else:28 print('用户名或密码错误')29 returnwapper30

31 @auth_func32 defindex():33 print('欢迎来到京东主页')34

35 @auth_func36 defhome(name):37 print('欢迎%s来到家目录' %name)38

39 @auth_func40 defshopping_car(name):41 print('欢迎来到购物车,%s的购物车里有[%s,%s,%s]' %(name,'洗面奶','牛奶','酸奶'))42

43 print('开始---------------------->',user_dic)44 index()45 print('结束---------------------->',user_dic)46

47 print('\n')48 print('开始---------------------->',user_dic)49 home('all is well')50 print('结束---------------------->',user_dic)51 print('\n')52

53 print('开始---------------------->',user_dic)54 shopping_car('all is well')55 print('结束---------------------->',user_dic)56

57 #################################################

58 #输出结果

59

60 开始----------------------> {'login': False, 'username': None}61 username: zhangsan62 password: 123

63 欢迎来到京东主页64 结束----------------------> {'login': True, 'username': 'zhangsan'}65

66

67 开始----------------------> {'login': True, 'username': 'zhangsan'}68 欢迎all iswell来到家目录69 结束----------------------> {'login': True, 'username': 'zhangsan'}70

71

72 开始----------------------> {'login': True, 'username': 'zhangsan'}73 欢迎来到购物车,all iswell的购物车里有[洗面奶,牛奶,酸奶]74 结束----------------------> {'login': True, 'username': 'zhangsan'}

无参数装饰器示例

带参数装饰器(给装饰器加上参数,参数为登录京东、访问家目录、访问购物车、加上不同的验证类型)

1 #!/usr/bin/env python

2 #-*- coding: utf-8 -*-

3

4 #用户列表

5 user_list =[6 {'name':'zhangsan','passwd':'123'},7 {'name':'lisi','passwd':'456'},8 {'name':'wangwu','passwd':'789'},9 ]10 #全局变量一改,其他子程序都会改,用来跟踪用户的登录状态

11 user_dic={'username':None,'login':False}12

13 #带参数装饰器

14 #要给装饰器传参数这里我们就多加一层auth来实现,最外面层传参数,最里层能收到。

15 def auth(auth_type='filedb'):16 defauth_func(func):17 def wapper(*args,**kwargs):18 if auth_type == 'auth_1':19 print("认证类型是", auth_type)20 if user_dic['username'] and user_dic['login']: #这里判断状态,session

21 res = func(*args, **kwargs)22 returnres23 username = input('username:').strip()24 passwod = input('password:').strip()25 for userdic inuser_list:26 if username == userdic['name'] and passwod == userdic['passwd']:27 user_dic['username'] =username28 user_dic['login'] =True29 res = func(*args,**kwargs)30 returnres31 else:32 print('用户名或密码错误')33 elif auth_type == 'auth_2':34 print("认证类型是", auth_type)35 res = func(*args, **kwargs)36 returnres37 else:38 print("不知道的类型")39 res = func(*args, **kwargs)40 returnres41 returnwapper42 returnauth_func43

44

45 @auth(auth_type='auth_1') #这里参数为auth_1

46 defindex():47 print('欢迎来到京东主页')48

49 @auth(auth_type='auth_2') #这里参数为auth_2

50 defhome(name):51 print('欢迎%s来到家目录' %name)52

53 @auth(auth_type='auth_3') #这里参数为auth_3

54 defshopping_car(name):55 print('欢迎来到购物车,%s的购物车里有[%s,%s,%s]' % (name, '洗面奶', '牛奶', '酸奶'))56

57 print('开始---------------------->',user_dic)58 index()59 print('结束---------------------->',user_dic)60

61 print('\n')62 print('开始---------------------->',user_dic)63 home('all is well')64 print('结束---------------------->',user_dic)65 print('\n')66

67 #################################################

68 #输出结果

69

70 开始----------------------> {'username': None, 'login': False}71 认证类型是 auth_172 username: zhangsan73 password: 123

74 欢迎来到京东主页75 结束----------------------> {'username': 'zhangsan', 'login': True}76

77

78 开始----------------------> {'username': 'zhangsan', 'login': True}79 认证类型是 auth_280 欢迎all iswell来到家目录81 结束----------------------> {'username': 'zhangsan', 'login': True}82

83

84 开始----------------------> {'username': 'zhangsan', 'login': True}85 不知道的类型86 欢迎来到购物车,all iswell的购物车里有[洗面奶,牛奶,酸奶]87 结束----------------------> {'username': 'zhangsan', 'login': True}

带参数装饰器示例

python 生成器装饰器_七.python迭代器生成器装饰器相关推荐

  1. python中高阶函数和装饰器_三.Python高阶函数和装饰器

    1高阶函数 1.1 数学概念回顾下数学知识: y=f(x) 这是最开始接触的普通函数 y=g(f(x)) 这个就是我们接触到的高阶函数 在数学和计算机科学中,高阶函数至少应当是满足下面一个条件的函数: ...

  2. python编写装饰器_写python中的装饰器

    python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器. 首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下) 1 de ...

  3. python类修饰器_《Python有什么好学的》之修饰器

    "Python有什么好学的"这句话可不是反问句,而是问句哦. 主要是煎鱼觉得太多的人觉得Python的语法较为简单,写出来的代码只要符合逻辑,不需要太多的学习即可,即可从一门其他语 ...

  4. python朋友圈表白_情人节「告白生成器」来了!这个AI能让偶像对你说情话,过于真实!...

    重磅干货,第一时间送达 情人节将至,当其他人还在苦思冥想如何准备情人节礼物时,我却已经收到了我最喜欢的idol说给我的情话视频-不仅如此,我还用自己的照片说出了亲爱的ta最喜欢的告白台词,究竟是什么技 ...

  5. python制作音乐模块_用Python打造一个只属于你的专属音乐播放器,享受动手的快乐!...

    平常我们总是用爬虫爬取网页上的音乐,今天我们换个玩法,用Python制作一个独一无二只属于你的音乐播放器,小伙伴们觉得如何?如果觉得提议还不错,那就立即动手吧! 一.需要的库 pygame tkint ...

  6. python编程免费小说_使用Python开发小说下载器,不再为下载小说而发愁

    有点荒废 这几天有点荒废,之前弃坑的网文<伏天氏>,这几天又给捡起来了.然后一发不可收拾的只想看小说,荒废了我的学习.在这里我要检讨啊..... 像我这样的穷人,看小说肯定是找免费的网站, ...

  7. python实现app自动签到器_利用Python实现App自动签到领取积分

    要自动签到,最简单的是打开页面分析请求,然后我们用脚本实现请求的自动化.但是发现食行没有页面,只有 APP,这不是一个好消息,这意味着需要抓包处理了. 有需要Python学习资料的小伙伴吗?小编整理[ ...

  8. python中级项目下载_中级Python复习:教程,项目思想和技巧

    python中级项目下载 本文旨在向Python初学者和开发人员介绍Python中使用的一些关键概念,这些概念一开始就没有讲授. 如果您可以创建二次方根求解器,则可以理解本文. 这些是我一天之内没有学 ...

  9. python十大语法_精华-Python十大语法有哪些?

    Python是某种象征简易观念的语言,其语法相比简易,特别容易入门.然而,假如此后小视Python语法的精妙和深邃,那便大错特错了.文中细致挑选了最能体现Python语法之精妙的十个知识要点,并另附完 ...

最新文章

  1. 上传图片并生成缩略图
  2. c程序设计语言中printf,编程序 用getchar函数读入两个字符c1和c2,然后分别用putchar和printf函数输出这两个字符。请问...
  3. VMware vsphere平台中部署 Oracle RAC(二、NTP配置和SSH信任)
  4. WCF中绑定的简单介绍
  5. 文献阅读:知识图谱数据管理研究综述
  6. 为什么我墙裂建议大家使用枚举来实现单例。
  7. 点击空链接,页面不跳到页头
  8. 音视频开发(28)---流媒体并发量与宽带、码率计算详解
  9. java # 折叠_如何在Java中实现列表折叠
  10. 我是怎么用缠论在商品里边抢钱之二 (2019-07-12 15:10:10)
  11. 前端js导出excel代码及出现的中文乱码和数字过长等问题的解决办法
  12. YYKit源码学习——YYMemoryCache
  13. MAC苹果应用软件,财务管理,三D制图,清理神器
  14. Studio3T连接远程服务器上的mongo数据库
  15. Android的资源引用(2)(Drawable)
  16. 北京医保可报销的定点医院
  17. 勾股定理的证明(转载)
  18. pycharm启动图片修改
  19. windowsXP命令集锦
  20. 搞明白这八个问题 Linux系统就好学多了

热门文章

  1. sql备份恢复数据库_使用DBATools通过SQL恢复数据库操作验证备份
  2. Object-C 学习笔记(IOS程序设计课程)01
  3. 禁用ViewPager边界滑动效果(转)
  4. stm32寄存器版学习笔记04 定时计数器中断
  5. 产生java的动态库文件so的配置步骤
  6. 测试转开发,一个女孩子短短的工作心得
  7. C#开发:openfiledialog的使用
  8. 最新公开的SEO优化公式
  9. android点击另一个app,Android 怎么从一个APP中打开另外一个APP
  10. SQL中PIVOT 使用