函数—函数进阶
Posted wqq0723
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数—函数进阶相关的知识,希望对你有一定的参考价值。
函数—函数进阶(二)
-
函数—函数进阶—列表生成式
1 #列表回顾 2 name = [2,5,7,9,4] 3 print(name) 4 for i in name: 5 print(i) 6 #结果为: 7 # [2, 5, 7, 9, 4] 8 # 2 9 # 5 10 # 7 11 # 9 12 # 4 13 14 #枚举 15 for index,i in enumerate(name): 16 print(index,i) 17 #结果为: 18 # 0 2 19 # 1 5 20 # 2 7 21 # 3 9 22 # 4 4 23 24 25 #问题:把列表里的每个值加1 26 #二逼青年版 27 a = [0,1,2,3,4,5,6,7,8,9] 28 print(a) #结果为:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 29 b = [] 30 for i in a:b.append(i+1) 31 print(b) #结果为:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 32 a = b #将b列表赋值给a列表 33 print(a) #结果为:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 34 35 #普通青年版 36 a = [0,1,2,3,4,5,6,7,8,9] 37 print(a) #结果为:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 38 for index,i in enumerate(a): #通过索引值增加 39 a[index] += 1 40 print(a) #结果为:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 41 42 #文艺青年版 43 a = [0,1,2,3,4,5,6,7,8,9] 44 print(a) #结果为:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 45 a = map(lambda x:x+1,a) 46 print(a) #结果为:<map object at 0x000001853C723FD0> 47 for i in a: 48 print(i) #结果为:1,2,3,4,5,6,7,8,9,10 49 50 51 #装逼青年版(列表生成式) 52 a = list(range(10)) 53 print(a) #结果为:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 54 a = [i+1 for i in a] #列表生成式 55 print(a) #结果为:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 56 57 a = [i for i in a] 58 print(a) #结果为:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 59 60 a = [i*i for i in a] 61 print(a) #结果为:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 62 63 #三元运算 64 b = list(range(10)) 65 print(b) #结果为:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 66 b = [i if i < 5 else i*i for i in b] 67 print(b) #结果为:[0, 1, 2, 3, 4, 25, 36, 49, 64, 81] 68 69 70 #既可以循环元组,字典,还可以循环字符串 71 c = ‘alexli‘ 72 c = [i for i in c] 73 print(c) #结果为:[‘a‘, ‘l‘, ‘e‘, ‘x‘, ‘l‘, ‘i‘] 74 75 #字符串可以相加 76 c = ‘alexli‘ 77 c = [i+‘w‘ for i in c] 78 print(c) #结果为:[‘aw‘, ‘lw‘, ‘ew‘, ‘xw‘, ‘lw‘, ‘iw‘] 79 80 #字符串可以相乘 81 c = ‘alexli‘ 82 c = [i*2 for i in c] 83 print(c) #结果为:[‘aa‘, ‘ll‘, ‘ee‘, ‘xx‘, ‘ll‘, ‘ii‘]
-
函数—函数进阶—生成器
通过列表生成式可以直接创建一个列表。但是受到内存限制,列表容量是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
如果列表元素可以按照某种算法推算出来,可以在循环的过程中不断推算出后续的元素。这样就不必创建完整的list,从而节省大量的空间。
在Python中,这种一边循环一边计算的机制,称为生成器:generator。
1 #创建一个包含1000个元素的列表 2 a = [i for i in range(1000)] 3 print(a) 4 5 #生成器(把一个列表生成式的[]改成(),就创建了一个generator ) 6 a2 = (i for i in range(1000)) 7 print(a2) #结果为:<generator object <genexpr> at 0x000002B27DF5A048> 8 print(next(a2)) #结果为:0 9 print(next(a2)) #结果为:1 10 print(next(a2)) #结果为:2 11 print(next(a2)) #结果为:3 12 print(next(a2)) #结果为:4 13 print(next(a2)) #结果为:5 14 print(next(a2)) #结果为:6 15 print(next(a2)) #结果为:7 16 print(next(a2)) #结果为:8 17 #停止 18 print(a2) #结果为:<generator object <genexpr> at 0x0000018F10C2A048> 19 #继续 20 print(next(a2)) #结果为:9 21 print(next(a2)) #结果为:10 22 print(next(a2)) #结果为:11 23 print(next(a2)) #结果为:12 24 25 #小结: 26 #使用next(a2)方法 27 #一个个的打印,可以打印1000个,不占用内存空间。 28 # 这种方法只能够向前,不能够后退。 29 #到最后的时候,会报错 30 31 a = (i for i in range(5)) 32 print(next(a)) #结果为:0 33 print(next(a)) #结果为:1 34 print(next(a)) #结果为:2 35 print(next(a)) #结果为:3 36 print(next(a)) #结果为:4 37 print(next(a)) #结果为:StopIteration
-
函数—函数进阶—斐波那契
1 #这种不断调用next(a)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象 2 #for 循环 3 a = (i for i in range(10)) 4 for i in a: 5 print(i) #结果为:0 1 2 3 4 5 6 7 8 9 6 7 #while 语句 8 while True: 9 print(next(a)) #结果为:0 1 2 3 4 5 6 7 8 9 但是会报错
1 #range就是生成器的原理生成的 2 ‘‘‘ 3 range在Python3与Python2中range的区别: 4 Python3(生成器): 5 E:Python>python3 6 Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.19 7 14 64 bit (AMD64)] on win32 8 Type "help", "copyright", "credits" or "license" for more informa 9 tion. 10 >>> range(100) 11 range(0, 100) 不会占用内存 12 13 Python2: 14 E:Python>python2 15 Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v. 16 1500 64 bit (AMD64)] on win32 17 Type "help", "copyright", "credits" or "license" for more informa 18 tion. 19 >>> range(10) 20 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 21 22 在Python2中,如何用生成器方式表示range: 23 E:Python>python2 24 Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit 25 (AMD64)] on win32 26 Type "help", "copyright", "credits" or "license" for more information. 27 >>> xrange(1000000) 28 xrange(1000000) 29 30 总结:Python2中的xrange(100000)等价于Python3中的range(100000) 31 ‘‘‘
1 #著名的斐波拉契数列(Fibonacci):除第一个和第二个数外,任意一个数都可由前两个数相加得到: 2 #1, 1, 2, 3, 5, 8, 13, 21, 34, ... 3 #斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易: 4 5 a,b = 1,2 6 print(a) #结果为:1 7 print(b) #结果为:2 8 9 #斐波那契数列 10 def fib(max): 11 n, a, b = 0, 0, 1 #n=0 a=0 b=1 12 while n < max: 13 print(b) 14 a, b = b, a+b #将b的值赋值给a,同时将a+b的值赋值给b 15 n = n + 1 16 return ‘done‘ 17 fib(15) #结果为:1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 18 19 # 赋值语句: a, b = b, a + b 20 # 相当于: 21 # t = a + b 22 # a = b 23 # b = t 24 25 26 #生成器(yield) 27 def fib(max): 28 n, a, b = 0, 0, 1 29 while n < max: 30 print(‘before yield‘) 31 yield b #yield的作用:把函数的执行过程冻结在这一步并且把b的值返回给外面的next()方法 32 print(b) 33 a, b = b, a+b 34 n = n + 1 35 return ‘done‘ 36 37 f = fib(15) #将功能转换成一个“生成器” 38 next(f) 39 next(f) 40 next(f) 41 next(f) 42 #结果为: 43 # before yield 44 # 1 45 # before yield 46 # 1 47 # before yield 48 # 2 49 # before yield 50 51 #小结: 52 # yield 把函数的执行过程冻结在了这一步 53 # 此时可以把 b 的值,返回给外面的 next() 方法 54 # 函数名添加(),内部代码不执行,只是生成一个生成器对象
-
函数—函数进阶—生成器调用方法
1 #生成器 2 a = (i for i in range(10)) 3 print(a) #结果为:<generator object <genexpr> at 0x0000022D719CA408> 4 print(next(a)) #结果为:0 5 print(next(a)) #结果为:1 6 print(next(a)) #结果为:2 7 print(next(a)) #结果为:3 8 print(next(a)) #结果为:4 9 print(next(a)) #结果为:5 10 11 #while 12 a = (i for i in range(10)) 13 while True: 14 print(next(a)) 15 16 #for 循环 17 a = (i for i in range(10)) 18 for i in a: 19 print(i) 20 ‘‘‘ 21 总结: 22 Python2: 23 range = list 24 xrange = 生成器 25 26 Python3: 27 range = 生成器 28 xrange 没有 29 ‘‘‘
-
函数—函数进阶—函数写生成器
1 ‘‘‘ 2 生成器的创建方式: 3 1、列表 生成 式 () 只能写一个三元运算 4 2、函数 5 ‘‘‘ 6 #函数 7 def range2(n): 8 count = 0 9 while count < n: 10 print(count) 11 count += 1 12 range2(10) #函数内部执行 13 14 15 #将函数变为生成器 16 def range2(n): 17 count = 0 18 while count < n: 19 print(‘count‘,count) 20 count += 1 21 yield count #类似return, yield 使程序冻结,next 解冻 22 range2(10) #因为 yield 没有返回结果 23 print(range2(10)) #结果为:<generator object range2 at 0x0000024840A7A408> 24 new_range = range2(10) 25 r1 = next(new_range) #结果为:count 0 26 print(r1) #结果为:1 27 print(‘干点别的事...‘) #结果为:干点别的事... 28 r2 = next(new_range) #结果为:count 2 29 print(r2) #结果为:2 30 31 # 除了使用next()方法外,还可以使用new_range.__next__() 32 new_range.__next__() #结果为:count 2 33 34 ‘‘‘ 35 小结 36 yield vs return 37 return 返回并且中止function 38 yield 返回数据并且冻结当前的执行过程 39 next 唤醒冻结的函数执行过程,继续执行,直到遇到下一个yield 40 ‘‘‘ 41 ‘‘‘ 42 生成器: 43 之前的函数从调用起,就必须等待执行结果结束,并返回计算值 44 生成器可以把函数整个运行过程中的结果,返回至外面 45 yield,是暂停的意思 46 ‘‘‘
-
函数—函数进阶—生成器send方法
1 # def range2(n): 2 # count = 0 3 # while count < n: 4 # print(‘count‘,count) 5 # count += 1 6 # yield count #类似于return,yield使程序冻结,next才解冻 7 # print(‘-------‘) 8 # return 333333 9 # 10 # new_range = range2(3) 11 # 12 # n1 = next(new_range) 13 # n2 = next(new_range) 14 # n3 = next(new_range) 15 # n4 = next(new_range) 16 # print(n3) 17 # print(n4) 18 19 ‘‘‘ 20 函数有了yield之后: 21 1、函数名称加(),就得到了一个生成器 22 2、return 在生成器里代表生成器的终止,直接报错 23 ‘‘‘ 24 25 def range2(n): 26 count = 0 27 while count < n: 28 print(‘count‘,count) 29 count += 1 30 sign = yield count #类似于return,yield使程序冻结,next才解冻 31 if sign == ‘stop‘: 32 print(‘--sign‘,sign) 33 break 34 return 333333 #函数中有了yield 就不会被执行了 35 36 new_range = range2(3) 37 n1 = next(new_range) 38 39 new_range.send(‘stop‘) 40 41 #send方法的作用: 42 #1、唤醒并继续执行,next方法只能唤醒 43 #2、发送一个信息到生成器内部
-
函数—函数进阶—迭代器
1 ‘‘‘ 2 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 3 4 一类是集合数据类型,如list、tuple、dict、set、str等; 5 6 一类是generator,包括生成器和带yield的generator function。 7 8 这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。 9 ‘‘‘ 10 #可以使用isinstance()判断一个对象是否是Iterable对象 11 from collections import Iterable 12 print(isinstance(‘abc‘,Iterable)) #结果为:True 13 print(isinstance(100,Iterable)) #结果为:False 14 print(isinstance([],Iterable)) #结果为:True 15 print(isinstance({ },Iterable)) #结果为:True 16 print(isinstance((x for x in range(10)),Iterable)) #结果为:True 17 18 #生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。 19 #可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。 20 21 #可以使用isinstance()判断一个对象是否是Iterator对象: 22 from collections import Iterator 23 print(isinstance((x for x in range(10)), Iterator)) #结果为:True 24 print(isinstance([], Iterator)) #结果为:False 25 print(isinstance({}, Iterator)) #结果为:False 26 print(isinstance(‘abc‘, Iterator)) #结果为:False 27 28 #生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。 29 30 #但是可以把list、dict、str等Iterable变成Iterator,使用iter()函数: 31 print(isinstance(iter([]), Iterator)) #结果为:True 32 print(isinstance(iter(‘abc‘), Iterator)) #结果为:True 33 34 ‘‘‘ 35 那么,为什么list、dict、str等数据类型不是Iterator? 36 37 因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。 38 可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据。 39 所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。 40 Iterator甚至可以表示一个无限大的数据流,例如,全体自然数。而使用list是永远不可能存储全体自然数的。 41 42 在当前的阶段,generator与Iterator基本是一致的。 43 44 小结: 45 1、凡是可作用于for循环的对象都是Iterable类型 46 2、凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列 47 3、集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。 48 4、Python3的for循环本质上就是通过不断调用next()函数实现的,例如: 49 50 for x in [1, 2, 3, 4, 5]: 51 pass 52 等价于: 53 it = iter([1, 2, 3, 4, 5]) 54 55 # 循环 56 while True: 57 try: 58 x = next(it) 59 except StopIteration: 60 break 61 ‘‘‘
以上是关于函数—函数进阶的主要内容,如果未能解决你的问题,请参考以下文章