day12-迭代器生成器和模块

有参装饰器

  1. 有参装饰器

    应用场景:如果实现装饰器的功能的时候需要额外的数据,就需要有参装饰器

    def 函数名(参数列表):

    ​ 定义无参装饰器函数

    ​ return 无参装饰器函数名

    函数名 - 创建装饰器的函数名

    参数名 - 有多个参数看实现装饰器的功能额外需要多少个数据

    def create_tag(name):
        def tag(f):
            def new_f(*args, **kwargs):
                result = f(*args, **kwargs)
                return f'<{name}>{result}</{name}>'
    
            return new_f
    
        return tag
    
    
    @create_tag('*')
    def func1():
        return 'abc'
    
    
    print(func1())
    
  • 练习:写个装饰器将原函数的返回值加上指定的数

    def create_tag(num):
        def add_num(f):
            def new_f(*args, **kwargs):
                result = f(*args, **kwargs)
                if type(result) in (int, float, bool, complex):
                    return result + num
                return result
    
            return new_f
    
        return add_num
    
    
    @create_tag(100)
    def func2():
        return 123
    
    print(func2())
    

迭代器

  1. 什么是迭代器(iter)
    1. 迭代器是容器型数据类型
    2. 迭代器无法直接获取所有的元素,只能一个一个的取(取指的是拿出来,而且只出不进);也无法通过len统计元素个数
    3. 创建迭代器的方法:a.将其他序列转换成迭代器 b.生成器
list1 = [1, 23, 41, 59]
i1 = iter(list1)
print(i1, type(i1))  # <list_iterator object at 0x0000012B37130E08> <class 'list_iterator'>
# print(len(i1))  - TypeError: object of type 'list_iterator' has no len()
  1. 获取元素

    不管以什么样的方式获取到了迭代器中的某个元素,那么这个元素在迭代器中就不存在了

    1. 获取单个元素

      next(迭代器)

    2. 遍历

      for 变量 in 迭代器:
      循环体

    i2 = iter('hello')
    print(next(i2))  # h
    print(next(i2))  # e
    print(next(i2))  # l
    print(next(i2))  # l
    print(next(i2))  # o
    # print(next(i2))  -  StopIteration
    
  • i3遍历结束后的时候,会变成空的迭代器

    i3 = iter(range(5))
    for x in i3:
        print(f'x:{x}')
    # print(next(i3))   -   StopIteration
    print(list(i3))     # []
    
    i4 = iter(range(0, 10, 2))
    # i4转换成列表后会变成空的迭代器
    print(list(i4))  # [0, 2, 4, 6, 8]
    # print(next(i4))  -  StopIteration
    

生成器

  1. 什么是生成器(generator)

    1. 感性的认识

      生成器是一种特殊的迭代器

      生成器可以理解成生产数据的机器,在存储的时候保存的时候产生数据的算法而不是数据本身

    2. 理性的认识

      调用带有yield关键字的函数就可以得到一个生成器

      (如果一个函数中有yield,那么调用这个函数不会执行函数体,也不会获取返回值,函数调用表达式的值是一个生成器对象)

  2. 这么创建生成器

    def func1():
        yield
        return 100
    
    
    result = func1()  # result就是一个生成器
    print(f'result:{result}')
    
  3. 生成器产生数据的能力怎么确定

    1. 能创建多少个数据?有哪些?
    • 看执行完生成器对应的函数会遇到几次yield,那么这个生成器就可以创造多少个数据
    • 每次遇到yield,yield后面的值是什么,对应创造的数据就是什么
    def func2():
        yield
        yield 10
        yield 100
    
    
    gen1 = func2()
    print(next(gen1))   # None
    print(next(gen1))   # 10
    print(next(gen1))   # 100
    # next(gen1)  -  StopIteration
    
    def func3():
        for x in range(5):
            yield 10**x
    
    
    gen2 = func3()
    for x in gen2:
        print(f'x:{x}')
    
  4. 生成器产生数据的原理

    生成器对应的函数在调用函数的时候不会执行函数体;获取生成器中的数据的时候才会执行函数体

    每次获取数据的时候,都是从上一次结束的位置开始执行函数体,直到遇到yield就停下来,将yield后面的数据作为结果,返回并且记录结束位置

    如果是next去取,执行的时候如果遇到函数结束都没有遇到yield就报错!

    def func4():
        print('======1======')
        yield 10
        print('======2======')
        yield 100
        print('======3======')
        yield 1000
        print('======4=====')
        yield 10000
        print('======end=====')
    
    gen3 = func4()
    print(f'第一次取:{next(gen3)}')
    print(f'第二次取:{next(gen3)}')
    for x in gen3:
        print(f'x:{x}')
    
  • 练习:写一个生成器能够产生指定前缀指定长度的学号

    前缀:py,长度4, py0001~py9999

    def create_num(front:str, length:int):
        for num in range(1, 10**length):
            """
            方法一:
            n = length-len(str(num))
            yield front + '0'*n + str(num)
            """
            # 方法二:
            # yield front+str(num).zfill(length)
            # 方法三:
            yield f'{front}{num:0>{length}d}'
    
    
    gen4= create_num('py', 4)
    

模块

  1. 什么是模块

    一个py文件就是一个模块

  2. 怎么在一个模块中使用另外一个模块的内容

注意:如果一个模块想要被其他的模块使用,那么这个模块在命名的时候必须符合标识符的要求

一个模块想要使用另一个模块中的内容,必须先导入:

  1. import 模块名 - 能够使用模块中所有的全局变量:使用的时候通过’模块名.'的方式

  2. from 模块名 import 变量名1, 变量名2, … - 能够使用模块中指定变量:变量直接使用

  3. 模块重命名:import 模块名 as 新模块名

  4. 变量重命名:from 模块名 import 变量 as 新变量名

  5. 导入所有变量:from 模块名 import *

    第一种导入方式:import

    import test
    print(test.test_a)
    
    test.test_func()
    

    第二种导入方式:from…import

    from test import test_a, test_func
    print(test_a)
    test_func()
    

    第三种导入方式:重命名

    import test as TS
    
    test = 'hello'
    print(test)
    
    TS.test_func()
    print(TS.test_a)
    

    第四种导入方式:变量重命名

    from test import x as test_x, test_func
    
    for x in range(10):
        print(f'x:{x}')
    
    print(test_x)
    
    test_func()
    

    第五种导入方式:通配符 *

    from test import *
    
    print(test_a)
    print(x)
    test_func()
    

导入模块的原理

  1. 原理

    当代码执行到导入模块的时候,系统会自动将被导入的模块中的代码全部执行一遍

    解决方案:

    if __name__ == '__main__':
    

    这个if语句中的代码在被别的模块导入的时候不会执行,if语句外面的会被执行,如果直接运行当前模块,模块这个if中的代码会被执行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值