zoukankan      html  css  js  c++  java
  • python基础篇笔记03 迭代器、生成器、推导式、内置函数

     
     
    D13 迭代器、生成器
     
     
    1.迭代器
     
      我们可以对 list,tuple,dict等类型的数据使用for循环从其中依次拿取数据进行使用,我们把这样的过程称为遍历。也叫迭代。
     
      可迭代对象: 把可以通过for循环迭代读取数据的对象称为可迭代对象。(都必须有 ‘__iter__’ 方法,即可迭代协议
       
      常见可迭代对象:  str , list , tuple , set , dict , f1文件句柄 , itertor迭代器(迭代器也是可迭代对象)
     
      dir(obj)  对象的所有操作方法
      可迭代对象的 dir(obj)里都有'__iter__'这个方法,可以用来判断是否是可迭代的
        if ‘__iter__’ in dir(obj)
         通常如此判断: from collections import Iterable (Iterator)从模块引包                   
                   isinstance(obj ,  Iterable)
     
      迭代器:
      在对数据迭代使用的过程中,都有个带状态的对象来帮助我们记录数据访问的位置。我们把这个帮助我们进行迭代的对象叫做迭代器
      (卡qia子zi)
          (迭代器必须有'__iter__', '__next__' 方法,即迭代器协议)  .__iter__() 返回迭代器自身, .__next__() 返回下一个值
     
           迭代器优点:  1、节省内存空间  2、满足惰性机制  3、不会反复取值
           附: try: ...... except: ....... 异常处理    (默认Exception 所有异常)
     
           可迭代对象转化成迭代器:iterob.__iter__()  console结果  iterator obj...
                           迭代器含有 __iter__   、 __next__  、 遵循迭代器协议
      
     
    for循环原理:
      (上卡qia子zi)
     
     
    2. 生成器    一种特殊的迭代器。(自主构建的特殊迭代器
     
      python中,生成器是一次生成并返回一个对象(生成器对象,它是一个特殊的迭代器),可将其视为可恢复函数
     
      简单的说,就是在函数的执行过程中,yield语句会把你需要的对象return返回给调用生成器的地方,然后hold保留状态退出函数,
      生成器内的所有变量参数都会被保存起来供下一次使用。下一次调用生成器函数的时候又从上次中断的地方( hold点)开始执行。 
             

      在python中有三种方式来构建生成器:

        1. 通过生成器推导式  g = (lambda x: x*i for i in rang(4))

        2. 通过生成器函数  yield 语句(相当于...return + hold...RH下次取值先找 hold点

                  yield  生成值

                  生成器函数+():只是代表一个生成器对象,并不是函数执行;

                          可理解为惰性机制,在不执行函数的前提下,获得(返回)该生成器对象

        3. python内置函数或者模块提供(其实2,3两种本质上差不多,都是通过函数的形式生成,

          只不过2是自己写的生成器函数,3是python提供的生成器函数而已)

    def func():
    
        print("111")
    
        yield 222
    
    gener = func() #  ()这个时候函数不会执行,()而是获取到生成器
    
    ret = gener.__next__() # 这个时候函数才会执行, 也可以用 next(gener)
    
    print(ret)
    
    运行结果:
    
    111
    
    222
    示例
      使用生成器获取生成值
        1. 使用 g.__next__()
        2. 使用 next(g)
        3. 使用 g.send()  (见下文)
     
     
      生成器函数(代表了生成器对象,即有生成器函数出现的地方就只是代表了该生成器对象,并不是函数执行。)
     
           第一 : 函数中只要有 yield ,就是特殊函数,是生成器函数
           第二 : 一个 yield 对应一个 __next__
     
              
     
     
     
       for  i  in  xxx  :  这个过程,就是将(可迭代对象)(容器)(迭代器)(生成器)xxx 中的元素挨个拿出来给临时的 i 
     
      关于生成器send:
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    
    def gen(name):
        print(f'{name} ready to eat')
        n = 100
        while 1:
            food = yield n
            print(food)
            print(f'{name} start to eat {food}')
            n = n + 1
    
    
    dog = gen('alex')
    # 第一次必须用next让指针停留在第一个yield后面 或者 send(None)
    
    ret = dog.send('骨头')
    # 与__next__一样,可以获取到yield的值
    # 还可以在本次执行__next__的过程中传入一个值,供生成器使用
    
    print(ret)
    示例1
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    
    def gen_demo():
        value = yield 1
        yield value
    
    
    gen = gen_demo()
    print(next(gen))
    print(gen.send("I am Value!"))
    示例2

      

      其实,send和next的执行很像,只是send可以和生成器互动,传入一个值。

     
     3.推导式、解析

      列表推导式分为两种模式:

        1.循环模式:[变量(加工的变量) for 变量 in iterable]

        2.循环筛选模式: [变量(加工的变量) for 变量 in iterable if 条件]

    1 li1 = [i for i in range(10)]
    2 li2 = [f'神舟{i}号' for i in range(1, 9)]
    3 li3 = [i for i in range(30) if i % 3 == 0]

      

      生成器表达式和列表推导式的语法上一模一样,只是把 [ ] 换成 ( ) 就行了。

      生成器推导式和列表推导式的区别:

        1.列表推导式比较耗内存,所有数据一次性加载到内存。而.生成器表达式遵循迭代器协议,逐个产生元素。

        2.得到的值不一样,列表推导式得到的是一个列表.生成器表达式获取的是一个生成器

        3.列表推导式一目了然,生成器表达式只是一个内存地址

     

    # 字典推导式 dic = {lst1[i]:lst2[i] for i in range(len(lst1))}

    # 集合推导式 s = {abs(i) for i in lst} 

     
     
    D14 内置函数
     
     
     
      函数就是以功能为导向,一个函数封装一个功能,那么Python将一些常用的功能(比如len)给我们封装成了一个一个的函数,供我们使用,
      他们不仅效率高(底层都是用C语言写的),而且是拿来即用,避免重复造轮子,那么这些函数就称为内置函数
     
    eval()  执行字符串类型的代码,并返回代码执行后最终结果。  
    exec()  执行字符串类型的代码,无返回值,即返回None  ---> 用于流程语句。
    eval('2 + 2')   # 4
    
    s = '''
    for i in [1,2,3]:
        print(i)
    '''
    exec(s)
    View Code
     
    hash()  获取一个对象(可哈希对象:int,str,Bool,tuple)的哈希值。
         字典的键Key唯一本质是指键Key哈希值唯一。
         hash(True)、hash(1)同为1,hash(False)、hash(0)同为0,所以对于字典,True跟1 是同名键,False跟0 是同名键。
    dict1 = {True: 'alex', 1: 'wusir'}
    print(dict1[True])    # wusir
    print(hash(True), hash(1)) # 1 1
    View Code
    help()  用于查看函数或模块用途的详细说明。
    callable()  用于检查一个对象是否是可调用的。如果返回True,object仍然可能调用失败;但如果返回False,调用对象ojbect绝对不会成功。
    int()  用于将一个字符串或数字转换为整型。
    print(int())
    print(int('12'))
    print(int(3.9))    # 并没有四舍五入
    print(int('0100', base=2))
    运行结果:
    0
    12
    3
    4
    View Code

    float()  用于将整数和字符串转换成浮点数。

    complex()  用于创建一个值为 real + imag * j 的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不能传入第二个参数。

    print(float(3))
    print(complex(1))
    print(complex(1, 2))
    print(complex('3+4j'))
    print(complex('12'))
    运行结果:
    3.0
    (1+0j)
    (1+2j)
    (3+4j)
    (12+0j)
    View Code
    bin()  十进制整数转二进制字符串(<class 'str'>)      
    oct()  十进制整数转八进制字符串   
    hex()  十进制整数转十六进制字符串
    print(bin(-10))
    print(oct(250))
    print(hex(250))
    运行结果:
    -0b1010
    0o372
    0xfa
    View Code
    divmod(x, y)  x除y,返回元组(商,余数)     
    round()  保留浮点数小数点位数,四舍五入                 
    pow(x,y,z=1)  x的y次幂,再对z取余(取模)
    print(divmod(7, 3))
    print(round(7 / 3))  # 默认不保留小数
    print(round(7 / 3, 2))
    print(round(2.333501, 3))  # 四舍五入
    print(pow(2, 3))
    print(pow(2, 3, 3))
    运行结果:
    (2, 1)
    2
    2.33
    2.334
    8
    2
    View Code

    bytes() 编码(编成 B码)。  str() 解释 B码

    s1 = '你好'  # 字符串'你好',两个字符'你'、'好'
    bs1 = s1.encode('utf-8')  # 编码=编译成字节码:把字符串中对字符编译成指定字节码 'utf-8'码
    print(bs1)  # b'xe4xbdxa0xe5xa5xbd'
    s1b = bs1.decode('utf-8')  # 解码=解释字节码:把特定字节码按照指定方式解释出来,解释成字符。(方式要一致才可)
    print(s1b)  # 你好
    bs2 = bytes(s1, encoding='utf-8')  # 编码
    print(bs2)  # b'xe4xbdxa0xe5xa5xbd'
    bs3 = bytes(s1, encoding='gbk')
    print(bs3)  # b'xc4xe3xbaxc3'
    print(bs3.decode('gbk'))  # 你好
    
    # 可用str()来进行解码操作,解释字节码=用指定方式把特定字节码转化成字符(串)。
    s2 = str(bs2, encoding='utf-8')
    print(s2)  # 你好
    s3 = str(bs3, encoding='gbk')
    print(s3)  # 你好
    View Code

    ord()  输入字符找该字符Unicode编码的位置(万国码)。

    chr()  输入Unicode位置数字找出其对应的字符。

    print(ord('A'))       # 65
    print(ord(''))     # 20013
    print(chr(97))      # a
    print(chr(20013))  #
    View Code

    repr()  返回一个对象的string形式(原形毕露)。

    dict1 = {'a': 1, 'b': 2}
    str1 = "abc哟!"
    str2 = repr(dict1)
    str3 = repr(str1)
    print(str2, type(str2))
    print(str3, type(str3))
    
    运行结果:
    {'a': 1, 'b': 2} <class 'str'>
    'abc哟!' <class 'str'>
    View Code
    enumerate(IterObj,n)   枚举函数
      对于一个可迭代对象,将其各个元素枚举编号打包成元组(),组成序列。编号从n开始
    list1 = ['a', 'b', 'c']
    for i in enumerate(list1):
        print(i)
    for i, j in enumerate(list1):
        print(i, j)
    for i, j in enumerate(list1, 10):
        print(i, j)
    运行结果:
    (0, 'a')
    (1, 'b')
    (2, 'c')
    0  a
    1  b
    2  c
    10  a
    11  b
    12  c
    View Code
     
    all()  全为真才为真,相当于and
    any()  有一个为真即为真,相当于or
    print()  屏幕输出
    ''' 源码分析
    def print(self, *args, sep=' ', end='
    ', file=None): 
    
        """
        print(value, ..., sep=' ', end='
    ', file=sys.stdout, flush=False)
        file:  默认是输出到屏幕,如果设置为文件句柄,输出到文件
        sep:   打印多个值之间的分隔符,默认为空格
        end:   每一次打印的结尾,默认为换行符
        flush: 立即把内容输出到流文件,不作缓存
        """
    
    '''print(111,222,333,sep='*')    # 111*222*333
    print(111,end='')
    print(222)    # 两行的结果 111222
    ​
    f = open('log','w',encoding='utf-8')
    print('重要学习资料...',file=f,flush=True)
    # 运行结果:屏幕无输出,log文件里写入了内容:'重要学习资料...'
    View Code

    list()  将一个可迭代对象转换成列表

    tuple()  将一个可迭代对象转换成元组

    dict()  通过相应的方式创建字典。

    l1 = list('abcd')
    tu1 = tuple('abcd')
    print(l1, tu1)
    运行结果:
    ['a', 'b', 'c', 'd'] ('a', 'b', 'c', 'd')
    View Code

    abs()  求绝对值

    sum()  求和

    print(sum([1, 2, 3]))
    print(sum((1, 2, 3), 100))
    运行结果:
    6
    106
    View Code

    min()  求最小值

    max()  求最大值

    print(min(-1, 0, 1))
    print(min([1, 2, 3]))  # 返回此序列的最小值
    print(min((-1, 2, 5), key=abs))
              # 加key是可以加函数名,就是加比较法则。
              # 就是将需要做比较的各元素,按照key所代表的函数法则进行最小值比较,最终仍旧返回对应的原始元素。
              #(即将各元素传参给法则函数,对返回值进行最小值比较)。
    print(min(-2, -1, 2, 5, key=lambda x: abs(x)))  # 可以设置多个参数比较大小。
    dic = {'a': 1, 'b': 2, 'c': 3}
    print(min(dic, key=lambda x: dic[x]))  
              # x为dic的键,函数法则就是键对应对值做最小值比较,最终返回对应对原始键。
    运行结果:
    -2
    1
    -1
    -1
    a
    View Code

    reversed()  翻转。若将一个序列翻转, 返回翻转序列的迭代器;序列即列表。

    l1 = reversed('你好')
    l2 = reversed((1, 2, 3, 4))
    l3 = reversed([1, 2, 3, 4])
    print(l1, type(l1))
    print(l2, type(l2))
    print(l3, type(l3))
    print(list(l1), list(l2), list(l3))
    运行结果:
    <reversed object at 0x0000000002193408> <class 'reversed'>
    <reversed object at 0x0000000002193448> <class 'reversed'>
    <list_reverseiterator object at 0x0000000002193488> <class 'list_reverseiterator'>
    ['', ''] [4, 3, 2, 1] [4, 3, 2, 1]
    View Code

    sorted()  排序,可以通过key加函数制定排序规则

    语法:  
      sorted(iterable,key=None,reverse=False)
    
    iterable : 可迭代对象
    
    key: 排序规则函数,sorted会将可迭代对象中的所有元素根据排序规则进行排序,(即将所有元素都传递给排序规则函数,按照运算的结果进行排序),
       经过规则排序后,sorted最终返回对应的原始元素的排序。
    
    reverse :是否是倒序,True 倒序 False 正序
    
    lst = [1,3,2,5,4]
    lst2 = sorted(lst)
    print(lst)    #原列表不会改变
    print(lst2)   #返回的新列表是经过排序的
     
     
    lst3 = sorted(lst,reverse=True)
    print(lst3)   #倒序
     
    结果:
    [1, 3, 2, 5, 4]
    [1, 2, 3, 4, 5]
    [5, 4, 3, 2, 1]
    
    字典使用sorted排序
    
    dic = {1:'a',3:'c',2:'b'}
    print(sorted(dic))   # 字典排序返回的就是键的排序
     
    结果:
    [1,2,3]
    
    
    
    
    和函数组合使用
    
    # 定义一个列表,然后根据一元素的长度排序
    lst = ['天龙八部','西游记','红楼梦','三国演义']
     
    # 计算字符串的长度
    def func(s):
        return len(s)
    print(sorted(lst,key=func))
     
    # 结果:
    # ['西游记', '红楼梦', '天龙八部', '三国演义']
    
    
    和lambda组合使用
    
    lst = ['天龙八部','西游记','红楼梦','三国演义']
     
    print(sorted(lst,key=lambda s:len(s)))
     
    结果:
    ['西游记', '红楼梦', '天龙八部', '三国演义']
     
     
    lst = [{'id':1,'name':'alex','age':18},
        {'id':2,'name':'wusir','age':17},
        {'id':3,'name':'taibai','age':16},]
     
    # 按照年龄对学生信息进行排序
     
    print(sorted(lst,key=lambda e:e['age']))
     
    结果:
    [{'id': 3, 'name': 'taibai', 'age': 16}, {'id': 2, 'name': 'wusir', 'age': 17}, {'id': 1, 'name': 'alex', 'age': 18}]
    View Code

    zip()  拉链方法。多个可迭代对象作为参数,功能:将多个对象中的元素按照索引对应拉在一起,组成元组,每个元组里都有一个这些可迭代对象的元素;返回一个迭代器

           若各个可迭代对象的元素个数不一致,则按照个数最少的返回。

    lst1 = [1, 2, 3]
    lst2 = ['a', 'b', 'c', 'd']
    lst3 = ('', '', '', '', '')
    print(zip(lst1, lst2, lst3))
    for i in zip(lst1, lst2, lst3):
        print(i)
    
    运行结果:
    <zip object at 0x00000000021C3648>
    (1, 'a', '')
    (2, 'b', '')
    (3, 'c', '')
    View Code
    filter()  筛选过滤函数  
      filter(func,xxx) xxx为可迭代对象
      将xxx中的每个元素依次实例化传参给函数func,筛选出xxx中满足条件的原始元素组成一个新的迭代器返回的是一个迭代器;
      func必须为条件函数,即func必须返回bool值,根据bool真假筛选,传递出xxx中条件判断为真的原始元素,组成一个新迭代器。
    语法: filter(function,iterable)
    
    function: 用来筛选的函数,在filter中会自动的把iterable中的元素传递给function,然后根据function返回的True或者False来判断是否保留此项数据
    
    iterable:可迭代对象
    
    lst = [{'id': 1, 'name': 'alex', 'age': 18},
           {'id': 1, 'name': 'wusir', 'age': 17},
           {'id': 1, 'name': 'taibai', 'age': 16}, ]
    
    ls = filter(lambda d: d['age'] > 16, lst)
    
    print(ls, type(ls))
    print(list(ls))
    
    运行结果:
    <filter object at 0x00000000021C3948> <class 'filter'>
    [{'id': 1, 'name': 'alex', 'age': 18}, {'id': 1, 'name': 'wusir', 'age': 17}]
    View Code
    map()  映射函数  
      map(func,xxx) xxx为可迭代对象
      将xxx中的每个元素依次实例化传参给函数func,传出经过函数处理的运算结果给一个新的迭代器,可看作加工。返回是一个迭代器
      func 必须为执行函数,即必须有返回值,map会传递出函数func 的返回值,组成一个新迭代器。
    映射函数
    
    语法: map(function,iterable)  功能:对可迭代对象中的每一个元素进映射,分别去执行function,执行结果组成一个迭代器。
    
    
    计算列表中每个元素的平方,返回新列表
    
    lst = [1,2,3,4,5]
    ​
    def func(s):
    ​
        return  s*s
    ​
    mp = map(func,lst)
    ​
    print(mp)
    ​
    print(list(mp))
    
    结果:
    <map object at 0x00000000023E34C8>
    [1, 4, 9, 16, 25]
    
    改写成lambda
    
    lst = [1,2,3,4,5]
    ​
    print(list(map(lambda s:s*s,lst)))
    
    
    计算两个列表中相同位置的数据的和
    
    lst1 = [1, 2, 3, 4, 5]
    ​
    lst2 = [2, 4, 6, 8, 10]
    ​
    print(list(map(lambda x, y: x+y, lst1, lst2)))
    ​
    结果:
    ​
    [3, 6, 9, 12, 15]
    View Code

    reduce()  递减函数

    from functools import reduce
    def func(x,y):
        return x + y
    ​
    # reduce 的使用方式:
    # reduce(函数名, 序列)  # 这两个参数必须都要有,缺一个不行
    ​
    ret = reduce(func,[3,4,5,6,7])
    print(ret)  # 结果 25
    
    
    reduce的功能:先把序列中的前俩个元素取出计算出一个值然后临时保存着,接下来用这个临时保存的值和序列中第三个元素进行计算,
    求出一个新的值将前面的临时值覆盖掉,然后在用这个新的临时值和列表中第四个元素计算,依次类推...最后reduce返回一个最终值。
    ​
    注意:我们放进去的序列没有更改
    
    以上这个例子我们使用sum就可以完全的实现了.我现在有[1,2,3,4]想让列表中的数变成1234,就要用到reduce了.
    
    普通函数版
    from functools import reduce
    ​
    def func(x,y):
    ​
        return x * 10 + y
        # 第一次的时候 x是1 y是2  x乘以10就是10,然后加上y也就是2最终结果是12然后临时存储起来了
        # 第二次的时候x是临时存储的值12 x乘以10就是 120 然后加上y也就是3最终结果是123临时存储起来了
        # 第三次的时候x是临时存储的值123 x乘以10就是 1230 然后加上y也就是4最终结果是1234然后返回了
    ​
    ret = reduce(func,[1,2,3,4])
    print(ret)
    
    ​结果:
    1234
    ​
    匿名函数版
    l = reduce(lambda x,y:x*10+y,[1,2,3,4])
    print(l)
    
    
    
    在Python2.x版本中recude是直接 import就可以的, Python3.x版本中需要从functools这个包中导入
    
    龟叔本打算将 lambda 和 reduce 都从全局名字空间都移除, 舆论说龟叔不喜欢lambda 和 reduce
    
    最后lambda没删除是因为和一个人写信写了好多封,进行交流然后把lambda保住了.
    View Code

    参考资料:https://www.processon.com/view/link/5b4ee15be4b0edb750de96ac

    compile()  编译函数  
          语法:compile(str,'','exec')  将一个字符串编译为字节代码对象。         
     
    format()  其中的数字格式化
    bytearry()  字节数组          
    memoryview()  内存对象    
    ascii()  判断是否是ASCII码表中的字符
     
     
                                                  
    3. 匿名函数
     
      匿名函数,顾名思义就是没有名字的函数。lambda是定义匿名函数的关键字,相当于函数的def。
     
      Func1 = lambda 参数1参数2返回值 
           
       
                    
     
     
     
     
     
    come on!
     
    all()   全为真才为真,相当于and
    any()   有一个为真即为真,相当于or
  • 相关阅读:
    Graphviz安装配置
    固定ip
    机器学习基础
    研究生入学感悟
    复试临时练习
    复试临时练习
    Dev-C++回文数遇到的小麻烦
    单例模式
    工厂方法模式
    Spark的checkpoint详解
  • 原文地址:https://www.cnblogs.com/kingon/p/11802454.html
Copyright © 2011-2022 走看看