zoukankan      html  css  js  c++  java
  • 14、迭代器协议、生成器、装饰器


    14.1、迭代器协议:

    1、迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回对象中的下一项,要么就引起一个StopIteration异常,以终止次迭

    代,迭代器协议规定迭代只能往后走,不能往前退;

    2、可迭代对象是指:实现了迭代器协议的对象,可迭代对象只能遍历一次,使用可迭代对象比较省内存空间,通常使用__iter__和__next__实现;

    3、协议是一种约定,可迭代对象实现了迭代器协议,python内部工具(如:for,sum,min,max函数等)使用迭代器协议访问可迭代对象;

    4、字符串,列表,元组,字典,集合,文件对象、这些都不是可迭代对象,只不过for循环调用了他们内部的__iter__()方法,把他们变成了

    可迭代对象;

    5、可迭代对象用法:

    (1)查看函数可用的方法:

    print(dir(set))


    (2)示例:

    1)

    x='hello'

    iter_test=x.__iter__()

    # 遵循迭代器协议,生成可迭代对象

    print(iter_test)

    # <str_iterator object at 0x00000182D0132EB8>

    # 输出的是可迭代对象

    print(iter_test.__next__())

    print(next(iter_test))

    # next(iter_test)---->iter_test.__next__()

    print(iter_test.__next__())

    print(iter_test.__next__())

    print(iter_test.__next__())

    # print(iter_test.__next__())

    # 如果超过迭代的元素会引起StopIteration异常


    2)

    l=[1,2,3,4,5]

    diedai_l=l.__iter__()

    while True:

    try:

    print(diedai_l.__next__())

    except StopIteration:

    print('迭代完毕了,循环终止了')

    break


    3)

    dic={'a':1,'b':2}

    iter_d=dic.__iter__()

    print(iter_d.__next__())

    print(iter_d.__next__())


    4)

    f=open('告白气球','r',encoding='utf8')

    iter_f=f.__iter__()

    print(iter_f)

    # <_io.TextIOWrapper name='告白气球' mode='r+' encoding='utf8'>

    print(iter_f.__next__(),end='')

    print(iter_f.__next__(),end='')


    5)

    f=open('告白气球','r',encoding='utf8')

    for i in f:

    print(i,end='')


    6)

    l = [1, 2]

    print(sum(l))

    # sum(l.__iter__().next+l.__iter__().next)


    7)最终写法:

    l=[1,2,3]

    for i in l: #i_l=l.__iter_() i=i_l.__next__()

    print(i)


    14.2、生成器:

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

    议)所以生成器就是可迭代对象;

    2、语法上和函数类似:生成器函数和常规函数几乎是一样的,它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,

    而常规函数使用return语句返回一个值;

    3、自动实现迭代器协议:对于生成器,Python会自动实现迭代器协议,以便应用到迭代背景中(如for循环,sum函数),由于生成器自动实现

    了迭代器协议,所以,我们可以调用它的next方法,并且在没有值可以返回的时候,生成器自动产生StopIteration异常;

    4、状态挂起:生成器使用yield语句返回一个值,yield语句挂起该生成器函数的状态,保留足够的信息,以便之后从它离开的地方继续执行;

    5、注意事项:生成器只能遍历一次

    6、使用生成器的优点:

    (1)优点一:生成器的好处是延迟计算,一次返回一个结果,也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用;

    #列表解析

    sum([i for i in range(100000000)]) #内存占用大,机器容易卡死

    #生成器表达式

    sum(i for i in range(100000000)) #几乎不占内存

    (2)优点二:生成器还能有效提高代码可读性

    7、生成器的用法:

    (1)普通用法:

    def test():

    yield 1

    yield 2

    yield 3

    g = test()

    # 获取生成器对象

    print(g)

    # <generator object test at 0x0000025B4D0C97C8>

    print(g.__next__())

    print(g.__next__())

    print(g.__next__())


    (2)使用三元表达式创建生成器:

    1)三元表达的使用(三元表达式只有三元,没有四元):

    name = 'chang'

    res = 'cool' if name == 'chang' else 'so cool'

    print(res)


    test = [i for i in range(10) if i > 5]

    print(test)


    test_list = []

    for i in range(10):

    test_list.append(i)

    print(test_list)

    #等价于

    l = [i for i in range(10)]

    print(l)


    2)示例:

    laomuji = ('鸡蛋%s' % i for i in range(5))

    # 生成器表达式

    print(laomuji)

    # <generator object <genexpr> at 0x0000022CA82A97C8>

    print(laomuji.__next__())

    print(laomuji.__next__())

    print(next(laomuji))

    print(next(laomuji))

    print(next(laomuji))

    #等价于

    laomuji = ('鸡蛋%s' % i for i in range(5))

    for i in laomuji:

    print("鸡蛋%s" %i)


    14.3、装饰器:

    1、装饰器定义:本质就是函数,功能是为其他函数添加新功能

    2、装饰器需要遵循的原则:

    (1)不修改被装饰函数的源代码

    (2)为被装饰函数添加新功能后,不修改被修饰函数的调用方式

    3、实现装饰器知识储备:

    装饰器=高阶函数+函数嵌套+闭包( 在一个作用域里放入定义变量,相当于打了一个包)

    4、装饰器的用法:

    import time



    def timmer(func):

    def wrapper(*args, **kwargs):

    start_time = time.time()

    res = func(*args, **kwargs)

    # 运行的是cal函数

    stop_time = time.time()

    print('函数运行时间是%s' % (stop_time - start_time))

    return res


    return wrapper



    @timmer

    # 语法糖@

    # @timmer就相当于cal=timmer(cal),返回的是wrapper的地址,执行cal()就是在执行wrapper()

    # cal=timmer(cal)=wrapper

    def cal(l):

    res = 0

    for i in l:

    time.sleep(0.1)

    res += i

    return res



    res = cal(range(20))

    print(res)
























  • 相关阅读:
    Python 模块 itertools
    Python 字符串的encode与decode
    python 模块 hashlib(提供多个不同的加密算法)
    暴力尝试安卓gesture.key
    hdu 1300 Pearls(DP)
    hdu 1232 畅通工程(并查集)
    hdu 1856 More is better(并查集)
    hdu 1198 Farm Irrigation(并查集)
    hdu 3635 Dragon Balls(并查集)
    hdu 3038 How Many Answers Are Wrong(并查集)
  • 原文地址:https://www.cnblogs.com/LiuChang-blog/p/12317209.html
Copyright © 2011-2022 走看看