zoukankan      html  css  js  c++  java
  • Python中的迭代器、生成器、装饰器

    1. 迭代器 

     1 """
     2     iterator
     3     迭代器协议: 对象必须提供一个next()方法,执行该方法要么返回迭代中的下一项,要么引起一个StopIteration异常,以终止迭代
     4     可迭代对象: 实现可迭代协议的对象。(对象内部定义一个__iter__()方法)
     5     访问方式:下标方式、迭代器协议、for循环
     6 """
     7 
     8 
     9 li = [1, 2, 3, 4, 5]
    10 iter_li = li.__iter__()  # 通过__iter__()方法生成可迭代对象
    11 print(iter_li)  # <list_iterator object at 0x000002565B5BD748>
    12 # print(li[0])
    13 print(iter_li.__next__())  # 1
    14 print(next(iter_li))  # 2
    15 
    16 # for 循环访问遵循迭代器访问方式
    17 # for i in li:
    18 #     print(i)

    2. 生成器

     1 """
     2     generator
     3     生成器函数: 定义函数,包换关键字 yield
     4     生成器表达式: 三元表达式
     5     send()
     6 """
     7 
     8 
     9 # 生成器函数
    10 def generator_func():
    11     yield 1
    12     yield 2
    13     yield 'louis'
    14     yield 'scar'
    15     yield 'rose'
    16     x = yield
    17     print('x=', x)
    18     y = yield
    19     print('y=', y)
    20 
    21 
    22 gen = generator_func()
    23 print(gen)  # <generator object generator_func at 0x000001A5464A2F48>
    24 print(gen.__next__())
    25 print(gen.__next__())
    26 print(gen.__next__())
    27 print(gen.__next__())
    28 print(gen.__next__())
    29 print(gen.__next__())  # None
    30 # 改变x的值并触发 __next()__
    31 res = gen.send('init_')
    32 print(res)  # x= init_ None
    33 
    34 # 生成器表达式
    35 count1 = [x for x in range(10)]  # 列表表达式
    36 print(count1)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    37 count2 = (x for x in range(10) if x > 5)  # 生成器表达式
    38 print(count2)  # <generator object <genexpr> at 0x000001E364E87840>
    39 print(list(count2))  # [6, 7, 8, 9]
    40 
    41 
    42 import time
    43 
    44 
    45 # 生产者消费者模型
    46 def consumer(name):
    47     print('消费者[%s]开始下单' % name)
    48     while True:
    49         num = yield
    50         time.sleep(0.5)
    51         print('%s 第[%s]杯奶茶' % (name, num))
    52 
    53 
    54 def producer():
    55     c1 = consumer('louis')
    56     c2 = consumer('scar')
    57     next(c1)
    58     next(c2)
    59     for i in range(1, 10):
    60         c1.send(i)
    61         c2.send(i)
    62 
    63 
    64 producer()

    运行结果:
    消费者[louis]开始下单
    消费者[scar]开始下单
    louis 第[1]杯奶茶
    scar 第[1]杯奶茶
    louis 第[2]杯奶茶
    scar 第[2]杯奶茶
    louis 第[3]杯奶茶
    scar 第[3]杯奶茶
    louis 第[4]杯奶茶
    scar 第[4]杯奶茶
    louis 第[5]杯奶茶
    scar 第[5]杯奶茶
    louis 第[6]杯奶茶
    scar 第[6]杯奶茶
    louis 第[7]杯奶茶
    scar 第[7]杯奶茶
    louis 第[8]杯奶茶
    scar 第[8]杯奶茶
    louis 第[9]杯奶茶
    scar 第[9]杯奶茶

    3 装饰器

      a. 装饰器实现日志操作(带参以及不带参的装饰器函数)

     1 """
     2     装饰器:本质就是函数,功能就是为其它函数添加附加功能
     3     使用场景: 插入日志、性能测试、事务处理、缓存、权限校验等
     4     语法糖: @def_func(func)
     5     装饰器 = 高阶函数 + 函数嵌套 + 闭包
     6     高阶函数: 函数的接受的参数是一个函数,返回值也是一个函数
     7     函数嵌套: 在函数里面执行其它函数
     8     闭包: 主要看作用域范围
     9 """
    10 import functools
    11 
    12 
    13 def func_logging(arg):
    14     print(arg)
    15     if callable(arg):  # 如果装饰器不带参数
    16         # @functools.wraps(arg)
    17         def _deco(*args, **kwargs):
    18             print('%s is running' % arg.__name__)
    19             arg(*args, **kwargs)
    20         return _deco
    21     else:  # 如果装饰器带参数
    22         def _deco(func):
    23             @functools.wraps(func)
    24             def __deco(*args, **kwargs):
    25                 if arg == 'warn':
    26                     print('warn %s is running' % func.__name__)
    27                 return func(*args, **kwargs)
    28             return __deco
    29         return _deco
    30 
    31 
    32 @func_logging  # test1 = func_logging(test)
    33 def test1():
    34     print('this is test1')
    35     print(test1.__name__)
    36 
    37 
    38 @func_logging('warn')  # 直接执行 func_logging() 返回装饰器函数 _deco()
    39 def test2():
    40     print('this is test2')
    41     print(test2.__name__)
    42 
    43 
    44 test1()
    45 # <function test1 at 0x000002335B5A1EA0>
    46 # test1 is running
    47 # this is test1
    48 # test1
    49 # 函数名变为_deco而不是test1,这个情况在使用反射的特性的时候就会造成问题。因此引入了functools.wraps解决这个问题
    50 test2()
    51 # warn
    52 # warn test2 is running
    53 # this is test2
    54 # test2

      b. 性能测试

     1 import time
     2 import functools
     3 # 性能测试
     4 def timer(func):
     5     @functools.wraps(func)
     6     def warpper(*args, **kwargs):
     7         print('%s is start running' % func.__name__)
     8         start_time = time.time()
     9         func(*args, **kwargs)
    10         stop_time = time.time()
    11         print('%s is stop running, cost %s s' % (func.__name__, stop_time - start_time))
    12     return warpper
    13 
    14 
    15 @timer
    16 def test3():
    17     time.sleep(1.0)
    18     print(test3.__name__)
    19 
    20 
    21 test3()
    22 # test3 is start running
    23 # test3
    24 # test3 is stop running, cost 1.0015299320220947 s
  • 相关阅读:
    如何紧急恢复SQL Server主数据库
    合理利用SQL Server查询执行计划
    理解RAID的四种级别
    sp_spaceused 显示行数、保留的磁盘空间以及当前数据库中的表、索引视图
    修复数据库索引问题:理解填充因数设置
    SQL Server调整因子
    sqlservr 命令行启动
    DBA需要考虑备份相关问题
    BCP
    “tablediff ”命令行工具
  • 原文地址:https://www.cnblogs.com/louiszh/p/12333404.html
Copyright © 2011-2022 走看看