zoukankan      html  css  js  c++  java
  • python的装饰器,迭代器用法

    装饰器、

    装饰器实际就是一个函数

    定义:在不改变内部代码和调用方式的基础上增加新的功能

    了解装饰器需要了解3个内容:

    1、函数即变量

    2、高阶函数

      1)、把一个函数名当作实参传给另一个函数

      2)、返回值中包含函数名

    例1:

    def test():  #定义函数test
        print('this is test func')   #打印(下方没有调用,所以不打印)
    
    def deco(func):  #定义函数deco,赋个形参(=test)
        print('this is deco')  #打印
        func()  #调用test函数
        return func  #返回值
    res = deco(test)  #调用test的内存地址
    print(res)  #打印test内存地址

    运行结果:

    例2:

    import time
    def test():
        time.sleep(3)    #睡3秒,期间不占内存
        print('this is test func')
    
    def deco(func):    #func = test
        start_time = time.time()    #开始执行的时间戳
        func()       #test()
        end_time = time.time()    #结束执行的时间戳
        print('this is run %s' % (end_time-start_time))    #执行所用的时间
        return func     #把test的内存地址返回给函数
    
    res = deco(test)
    print(res)

    运行结果:

    3、嵌套函数

    嵌套函数,调用时需要,一层一层的调用

    def test():
        def deco():
            print('this is test')
        deco()
    test()

    运行结果:

    装饰器练习

     例1:普通装饰器

    给下面的函数添加新功能

    def test():
        print('this is test')
    test()

    需要定义一个新函数进行添加

    def deco(func):     #形参
        def wrapper():
            func()
            print('新功能')  #用打印代替新功能
        return wrapper

    原函数调用新函数

    def test():
        print('this is test')
    result = deco(test)  #定义变量接收repper的内存地址
    result()

    为了不使原函数的调用方式更改,将变量result 换成 test接收

    def test():
        print('this is test')
    test = deco(test) 
    test()

    为了不更改原函数代码,用@放在原函数前,来代替函数中的“rest = drco(test)”

    def deco(func): 
        def wrapper():
            func()
            print('新功能')
        return wrapper
    
    @deco
    def test():
        print('this is test')
    test()

    运行结果:

    例2:带参数的装饰器

    如果原函数带传参数的情况

    def test(name):
        print('my name is %s '% name)
    test('aaa')

    那么添加新功能时,需要添加参数

    def deco(func):    
        def wrapper(name):     #传参数
            func(name)     #传参数
            print('新功能') 
        return wrapper

    如果原函数参数很多

    def test(name, age, job):
        print('my name is %s, my age is %s, my job is %s'% (name, age, job))
    test('aaa', 18, 'IT')

    那么我们添加功能的函数时也要添加所有的参数

    def deco(func):    
        def wrapper(name, age, job):     #传参数
            func(name, age, job)     #传参数
            print('新功能') 
        return wrapper

    因为比较麻烦所以传参数的快捷方式,不用考虑参数个数

    def deco(func):
        def wrapper(*args, **kwargs):
            func(*args, **kwargs) 
            print('新功能')
        return wrapper 
    @deco
    def test(name, age, job):
        print('my name is %s, my age is %s, my job is %s'% (name, age, job))
    test('aaa', 18, 'IT')

    运行结果:

    迭代器、迭代的工具

    什么是迭代:指的是一个重复的过程,每一次重复称为一次迭代,并且每一次重复的结果是下一次重复的初始值

    while True:
        print('hello world')

    上面这种方式只有重复,结果并不是下一次的初始,所以不是迭代

    例:不用for循环,用while循环将下边几种数据类型逐个取出

    字符串:s = 'helloworld'

    列表:l = ['a','b','c','d','e']

    元组:t = ('a','b','c','d','e')

    字典:dict1 = {'name' : 'aaa', 'age' : 18, 'job' : 'IT'}

    集合:set1 = {'a','b','c','d','e'}

    文件:f = open('a.txt', 'w', encoding='utf-8')

    整数:12345 (不能迭代)

    1 = 0
    while 1 < len(set1):
        print(set1[i])
        i += 1

    如果经过上边的循环进行测试会发现:

    对于序列类型的字符串,列表,元组可以依赖于索引来迭代取值,

    但是字典,集合,文件却不行,所以,python必须为我们提供一种不依赖于索引取值的方法,就是迭代器

    可迭代对象

    判断是否是可迭代对象

    可以在pycharm软件中试验,如果有"xx.__iter__"这种用法那么就是能变成可迭代对象

    "xx.__iter__"就是把一个对象变成可迭代对象"xx.__iter__" 可以简写成 "iter(xx)"

    迭代器对象

    "xx.__iter__""xx__next__"这两种方法的就是迭代器对象

    print(f is f.__iter__())  #f是上边的文件类型

     运行结果:由此看出,文件类型本身就是可迭代对象

     next方式取值

    dict1 = {'name' : 'aaa', 'age' : 18, 'job' : 'IT'}
    d_items = dict1.__iter__()
    res = d_items.__next__()
    res1 = d_items.__next__()
    res2 = d_items.__next__()
    print(res)

    可以调取 res,res1,res2,分别是三个key然后就可以根据key的来调取值了,"xx.__next__()" 可以简写成 "next()"

    但是它每取一个值要多一条代码,只能一个一个取,迭代器优点:同一时间在内存里只有一个值,节省内存空间

    若想一起取,所以我们要采用while方式

    dict1 = {'name' : 'aaa', 'age' : 18, 'job' : 'IT'}
    d_items = dict1.__iter__()
    while True:
        res = d_items.__next__()
        print(res)

    因为系统会停止迭代报错

    运行结果:

    异常处理:try....except +错误

    dict1 = {'name' : 'aaa', 'age' : 18, 'job' : 'IT'}
    d_items = dict1.__iter__()
    while True:
        try:
            res = d_items.__next__()
            print(res)
        except StopIteration:
            break

    运行结果:,这样就可以取值了,

     通过以上的步骤,我们知道了取值的原理及过程,这个原理同样也是for循环的原理

    dict1 = {'name' : 'aaa', 'age' : 18, 'job' : 'IT'}
    for i in dict1:     #相当于dict1.__iter__(),即变成可迭代对象
        print(i)

    运行结果:

    总结

    可迭代对象不一定是迭代器对象

    迭代器对象一定是可迭代对象

  • 相关阅读:
    面试题--十进制转换成2进制
    c++基础--如何将函数作为参数传递
    面试题--完全二叉树的的最后一层的最右节点
    数据库原理--故障恢复
    数据库原理--事务并发控制
    数据库原理--事务(一)
    数据库原理--1nf 2nf 3nf
    数据库原理--外键和主键
    数据库原理--函数依赖和范式
    人人都有极客精神
  • 原文地址:https://www.cnblogs.com/liketimes/p/10001263.html
Copyright © 2011-2022 走看看