Day 10 - 迭代器和生成器

Day 10

迭代器和生成器

迭代器
  • 说明:

    迭代器时容器型数据类型(iter)

    有如下特点:

    1.不能同时直接查看所有元素(打印看不到其中元素)

    2.不能直接统计个数

    3.元素只能单个获取(每次获取最上层元素)

    4.每次获取元素,元素都会从迭代器消失

  • 创建迭代器

    1.通过iter函数将其他序列转换为迭代器

    2.通过生成器创建

    iter1 = iter([1, 2, 3, 4])
    iter2 = iter('abcde')
    print(iter1, type(iter1))               # <list_iterator object at 0x00000274DFBCE748> <class 'list_iterator'>
    print(iter2, type(iter2))               # <str_iterator object at 0x00000274DFBCEA20> <class 'str_iterator'>
    # print(len(iter1))                     # 报错 - object of type 'list_iterator' has no len()
    
  • 获取迭代器元素

    语法:

    1.获取单个元素

    next(iteration)- 获取迭代器最上层的一个数据

    2.遍历

    for variable in iteration:

    说明:

    不管通过什么方式获取到迭代器中的元素,对应的元素都会从迭代器消失

    print(next(iter1))                      # 1
    print(next(iter1))                      # 2
    next(iter1)
    print(next(iter1))                      # 4
    # next(iter1)                           # 报错 - StopIteration(迭代器为空)
    for i in iter2:
        print(i)
    
生成器
  • 说明:

    迭代器的特点和元素获取方式都适用

    调用一个带有yield关键字的函数就可以创建一个生成器对象(如果被调用的函数里面有yield,不会执行函数体,也不会获取函数返回值)

    # 尝试yield在不同位置会有什么变化
    def func1():
        yield
        print('abcde')
        # yield
        print([1, 2, 3, 4])
        # yield
        return 0
        # yield
    
    gen1 = func1()
    print(gen1)
    
  • 确定生成器产生的数据

    产生数据的个数:执行生成器对应的函数执行时会遇到的yield数量

    产生的数据的值:每次遇到的yield后面的数据,没有数据就是None

    def func3(x):
        yield 10
        if x & 1:
            yield 20
        return 30
        yield 30
    
    gen3 = func3(5)
    print(list(gen3))               # [10, 20]
    gen4 = func3(4)
    print(list(gen4))               # [10]
    
  • 生成器原理

    调用函数创建生成器对象的时候不会执行函数体,获取生成器中的元素的时候才会执行

    第一次获取元素会从函数体开始位置开始执行,执行到第一次yield时暂停,并且将yield后面的数据作为这次获取到的元素

    之后每次获取元素都会从上次暂停的位置向后执行,执行到yield时又会暂停

    当某一次执行时到函数结束都没有遇到yield,用next获取元素时会报错 - StopIteration

    def func4():
        print('=1=')
        yield 100
        print('=2=')
        yield 200
        print('=3=')
        yield 300
    
    print(next(func4()))            # =1= 100
    print(next(func4()))            # =1= 100
    gen5 = func4()
    gen6 = func4()
    print(next(gen5))               # =1= 100
    x = next(gen5)                  # =2=
    print(x)                        # 200
    print(next(gen5))               # =2= =3= 300
    # next(gen5)                    # 报错 - StopIteration
    print(next(gen6))               # =1= 100(不会报错)
    
    # 编写一个产生一个学号的生成器,生成001~999的学生学号
    # Python001~Python999 or Java001~Java999
    def produce_num(project: str):
        for i in range(1, 1000):
            # 方法一:
            if i < 10:
                yield f'{project}00{i}'
            elif i < 100:
                yield f'{project}0{i}'
            else:
                yield project + str(i)
            
            # 方法二:
            yield f'{project}{i:0>3}'
            
            # 方法三:
            yield project + str(i).zfill(3)
    
    python_num = produce_num('Python')
    # print(list(python_num))
    java_num = produce_num('Java')
    # print(next(java_num))
    
    
    # 编写一个偶数生成器,产生正偶数
    def produce_even():
        num = 0
        while True:
            yield num
            num += 2
    
    num = produce_even()
    print(next(num))
    print(next(num))
    print(next(num))
    print(next(num))
    print(next(num))
    for _ in range(50):
        print(next(num))
    
  • 生成式 - 生成器的推导式

    说明:

    将列表推导式的 [] 变换为()即为生成器的推导式

    gen_crate = ('str1' if z == 0 else f'str{z}' for z in range(0, 100, 3))
    print(gen_crate)
    print(next(gen_crate))
    print(next(gen_crate))
    print(next(gen_crate))
    print(next(gen_crate))
    
模块
  • 说明:

    在Python中一个py文件就是一个模块(可以在一个模块中使用另外一个模块(同一工程项目下)的内容,在使用前要导入模块)

    只有全局变量、全局函数、全局类才能导入,统称为(广义)全局变量

  • 导入模块

    1.import 模块名(module’s name)- 使用模块中所有的全局变量;以module_name.variable的方式使用

    2.from module_name import variable1, variable2,…… - 导入指定模块中指定的全局变量;可以直接使用变量

    3.import module_name as new_name - 导入模块并用new_name命名;以new_name.variable的方式使用

    4.from module_name import variable1 as new_variable1, variable2,…… - 导入模块中的变量并重命名某些变量;直接使用新变量或变量

    5.from module_name import * - 导入模块中所有全局变量

    • 注意:

      import函数自带查重功能(导入多次也只会执行一次)

  • 导入原理

    不管是通过import还是from import,在导入模块时,系统会自动将被导入的模块中的所有代码运行一次

  • 书写规范

    在定义模块时,可以通过if __name__ == "__main__":这个if语句来阻止模块中指定代码在被其他模块导入时执行(在这个if语句中的代码不会被其他模块执行,不在if语句中的代码会被其他模块执行)

    每个模块都会自带一个__name__变量,在没有运行模块时,__name__的值为当前__name__所在文件的文件名;在模块直接运行时__name__的值会变为"__main__",间接运行或不执行时__name__的值不会发生改变

    def function1()
        pass
    def function2()
        pass
    ……
    def functionN()
        pass
    ……
    
    def main()
        function1()
        function2()
        functionN()
        ……
    
    if __name__ == "__main__":
        main()
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值