Day 13 迭代器,生成器,内置函数

1.迭代器

  1. 可迭代对象:内部还有__iter__方法的对象叫做可迭代对象
  2. 迭代器对象:内部既有__iter__方法,又含有__next__方法的对象叫做迭代器对象
  3. 迭代器一定是可迭代对象,可迭代对象不一定是迭代器对象
  4. 可迭代对象常用数据类型(list,tuple,str,set,dict,文件句柄)      文件句柄属于迭代器对象  
  5. 可迭代对象使用__iter__(iter())方法可以生成一个迭代器
    list1 = [1, 2, 3, 4, 5, 6]
    print(list1.__iter__())  # <list_iterator object at 0x000002A6FECB71D0> 返回一个迭代器对象
    list1 = [1, 2, 3, 4, 5, 6]
    l = iter(list1)
    print(l)  # <list_iterator object at 0x0000025809147390>
    l1 = iter(l)    # 迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本身
    print(l1)  # <list_iterator object at 0x0000025809147390>

     

  6. 迭代器通过__next__方法一个一个元素取值,当取完里面所有元素后,继续取值会触发StopIteration异常,next方法只能向后依次取值,不可逆
    list1 = [1, 2, 3, 4, 5, ]
    l = iter(list1)
    print(l.__next__())  # 1
    print(l.__next__())  # 2
    print(l.__next__())  # 3
    print(l.__next__())  # 4
    print(l.__next__())  # 5
    print(l.__next__())  # StopInteration

     

  7. __next__方法取值的优点是不依赖索引取值,内存中只有一份内存空间不会导致内存溢出,缺点是不能获取指定的元素,取值完以后会触发StopIteration异常
  8. for 循环的本质 1:将in后的对象调用iter()方法得到一个迭代器  2 通过next 方法取值   3 捕获StopIteration异常,当报错自动终止循环
    list1 = [1, 2, 3, 4, 5, 6]
    iter_list = iter(list1)
    while 1:
        try:
            print(iter_list.__next__())
        except StopIteration:
            break

     

2.生成器:本质就是迭代器,只不过是用户自定义的迭代器

  1. yield 关键字:yield后面跟的值就是调用迭代器__next__方法能得到的值,yield既可以返回一个值也可以返回多个值,返回多个值的时候以元组的方式返回,函数内部如果有yield关键字,那么加括号调用函数时并不会触发函数内部函数体的运行,而是得到一个生成器
    # 自写range()函数
    def my_range(x,y,z=1):
        while x < y:
            yield x
            x += z
    
    for i in my_range(1,10,2):
        print(i,end=' ')  # 1 3 5 7 9

     

  2. yield 传参:
    def sport(name):
        print(f'{name}开始运动')
        while 1:
            game = yield
            print(f'{name}开始{game}')
    
    g = sport('小明')
    # 当函数内有yield关键字的时候,调用该函数不会执行函数体代码,而是将函数变成生成器
    g.__next__()   # 小明开始运动 必须先将代码运行至yield 才能够为其传值
    g.send('踢足球')  # 为函数中game传值并调用 __next__()方法 小明开始踢足球
    g.send('跑步')  # 小明开始跑步

     

  3. yield 与 return 的异同点  相同点: 都可以返回值   不同点 yield可以返回多次值,而return返回值后直接结束函数, yield还可以传参
  4. yield面试题分解:
    def add(n,i):
        return n+i
    def test():
        for i in range(4):
            yield i
    g=test()   # 不会执行
    for n in [1,10]:   # 不会执行
        g=(add(n,i) for i in g)
        # 第一次for循环g=(add(n,i) for i in test())
        # 第二次for循环g=(add(n,i) for i in (add(n,i) for i in test()))
    res=list(g)  # 基于for 循环.此时执行所有的生成器内部的代码
    print(res)   # [20, 21, 22, 23]
    """
    for i in (add(10,i) for i in test()):  会执行所有的生成器内部的代码
        add(n,i)
    """

     

3.内置函数

  1. abs()  绝对值 
    print(abs(-5))  # 5
    print(abs(5))  # 5
  2. all() , any()  判断一个可迭代对象是否有bool值为False的元素 
    l = ['', 'a', 'b']
    print(all(l))  # False 只要有一个为False就返回False
    print(any(l))  # True 只要有一个为True 就返回True
  3. bin(),oct(),hex()  
    print(bin(10))  # 0b1010 10转2
    print(oct(10))  # 0o12 10转8
    print(hex(10))  # 0xa 10转16
  4. bytes() 
    s = 'hello'
    print(bytes(s,encoding='utf-8'))  # b'hello' 将字符串转化为bytes类型
  5. callable() 判断对象是否可调用
    s = 'hello'
    def func():
        pass
    print(callable(s))  # False
    print(callable(func)) # True
  6. chr() ord()
    print(chr(97))  # 将数字转换成ascii码表对应的字符
    print(ord('a'))  # 将字符按照ascii表转成对应的数字
  7. dir()  获取当前对象名称空间里面的名字
    l = [1, 2, 3, 4, 5]
    print(dir(l))
    '''
    ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
    
    '''
  8. divmod()  求商数余数
    a, b = divmod(100,9)
    print(a,b)  # 商为11,余1
  9. enumerate() 枚举
    l = ['a', 'b', 'c', 'd']
    for index,i in enumerate(l):
        print(index,i,end=' ')  # 0 a 1 b 2 c 3 d 
  10. eval() 将字符串当作代码来执行,支持简单的,不支持逻辑运算,不支持赋值运算
    s = 'print(1 + 2)'
    eval(s)   # 3
  11. exct()  将字符串当作代码来执行
    s = '''
    for i in range(5):
        print(i,end=" ")
    '''
    exec(s)   # 0 1 2 3 4 
  12. globals():查看全局命名空间里的名字:
    print(globals())  # '__name__': '__main__', '__doc__': None, '__package__'....
    def func():
        name = 'xiaoming'
        print(globals())  # '__name__': '__main__', '__doc__': None, '__package__'.....
    # 无论在哪里都查看的是全局名称空间里的名字
    func()
  13. locals():查看所在命名空间里的名字
    print(locals())   # {'__name__': '__main__', '__doc__': None, '__package__': None...
    def func():
        name = 'xiaoming'
        print(locals())    # {'name': 'xiaoming'}
    
    func()
  14. isinstans()  判断对象是否属于某个数据类型
    a = 1
    print(isinstance(a,int))  # True 判断变量a是否是int类型
  15. sum() 求和: 
    print(sum([2,4,5,6]))  # 17 
  16. round()  对浮点数进行四舍五入处理
    print(round(5.4))  # 5
    print(round(5.5))  # 6
  17. pow 幂运算
    print(pow(2,3))  # 2**3  8

     

posted @ 2019-07-15 17:31  人生能有几回搏  阅读(173)  评论(0编辑  收藏  举报