zoukankan      html  css  js  c++  java
  • 函数—函数进阶(二)

                                          函数—函数进阶(二)

    •  函数—函数进阶—列表生成式

     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 '''
  • 相关阅读:
    OpenSSL证书生成
    支付宝支付流程
    前端获取用户位置信息
    微信公众号开发(三)
    微信公众号开发(二)
    微信公众号开发(一)
    前端优化
    页面自适应
    CSS样式(二)
    CSS样式(一)
  • 原文地址:https://www.cnblogs.com/wqq0723/p/9620604.html
Copyright © 2011-2022 走看看