zoukankan      html  css  js  c++  java
  • Python学习——迭代器&生成器&装饰器

    一、迭代器

          迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合

    特点:

    1. 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
    2. 不能随机访问集合中的某个值 ,只能从头到尾依次访问
    3. 访问到一半时不能往回退
    4. 便于循环比较大的数据集合,节省内存

    生成一个迭代器:

     1 >>> a= iter([1,2,3,4,5])
     2 >>> a
     3 <list_iterator object at 0x0044ADF0>
     4 
     5 >>> a.__next__()
     6 1
     7 >>> a.__next__()
     8 2
     9 >>> a.__next__()
    10 3

    二、生成器

      一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器

    代码:

     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 '''
     4 # @time    : 2017/4/22 1:00
     5 # @author  : huange
     6 # @version : 1.1
     7 # @file    : test2.py
     8 # @Software: PyCharm
     9 '''
    10 
    11 def out_money(totle):
    12 
    13     while totle > 0:
    14 
    15         totle -= 1
    16 
    17         yield 1                             # yield 返回一个值
    18 
    19 
    20 ATM = out_money(3)
    21 
    22 print("取到钱 %s 万" % ATM.__next__())
    23 
    24 print("花掉花掉!")
    25 
    26 print("取到钱 %s 万" % ATM.__next__())
    27 
    28 print("花掉花掉!")
    29 
    30 print("取到钱 %s 万" % ATM.__next__())
    31 
    32 print("花掉花掉!")
    33 
    34 print("取到钱 %s 万" % ATM.__next__())    # 到这时钱就取没了,再取就报错了
    35 
    36 print("取到钱 %s 万" % ATM.__next__())

    这个yield的主要效果呢,就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以再重新调用这个函数,从上次yield的下一句开始执行。

    可以通过yield实现在单线程的情况下实现并发运算效果

     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 '''
     4 # @time    : 2017/4/22 1:00
     5 # @author  : huange
     6 # @version : 1.1
     7 # @file    : test2.py
     8 # @Software: PyCharm
     9 '''
    10 
    11 import time
    12 
    13 def consumer(name):
    14     print("%s 准备吃包子了!" %name)
    15     while True:
    16         baozi = yield                    # yield 通过 send()方法接收值
    17         print("包子[%s]来了,被[%s]吃了" %(baozi,name))
    18 
    19 def producer(name):
    20     c1 = consumer('A')
    21     c2 = consumer('B')
    22     c3 = consumer('C')
    23 
    24     c1.__next__()
    25     c2.__next__()
    26     c3.__next__()
    27 
    28     print("%s 开始准备做包子了!" % name)
    29 
    30     for i in range(10):
    31         time.sleep(1)
    32         print('做了3个包子')
    33         c1.send(i)
    34         c2.send(i)
    35         c3.send(i)
    36 
    37 producer('hh')


    三、装饰器

     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 '''
     4 # @time    : 2017/4/24 20:29
     5 # @author  : huange
     6 # @version : 1.1
     7 # @file    : 装饰器.py
     8 # @Software: PyCharm
     9 '''
    10 
    11 # @login内部会执行一下操作:
    12 # 1.执行login函数,并将 @login 下面的 函数 作为login函数的参数,即:@login 等价于 login(movie)
    13 # 2.•将执行完的 login 函数返回值赋值给@login下面的函数的函数名
    14 
    15 def login(func):
    16     def inner(*args,**kwargs):
    17         print("login success...")
    18         return func(*args,**kwargs)
    19     return inner
    20 
    21 def home():
    22     print("welcome to Home...")
    23 
    24 
    25 @login
    26 def movie(name,passwd):
    27     print("welcome [%s] [%s] to movie...." % (name,passwd))
    28 
    29 @login
    30 def music(name):
    31     print("welcome [%s] to music..." % name)
    32 
    33 movie('huhuan','123')
    34 music('huhuan')
    35 home()

    如上所示:被装饰的函数带有不同个数的参数,因此,装饰器需要用到动态参数!

    一个函数可以被多个装饰器装饰:

     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 '''
     4 # @time    : 2017/4/24 20:29
     5 # @author  : huange
     6 # @version : 1.1
     7 # @file    : 装饰器.py
     8 # @Software: PyCharm
     9 '''
    10 # 验证登陆
    11 def login(func):
    12     def inner(*args,**kwargs):
    13         print("login success...")
    14         return func(*args,**kwargs)
    15     return inner
    16 
    17 # 验证是否是会员用户
    18 def member(func):
    19     def inner(*args,**kwargs):
    20         print("welcome member...")
    21         return func(*args,**kwargs)
    22     return inner
    23 
    24 def home():
    25     print("welcome to Home...")
    26 
    27 # @login内部会执行一下操作:
    28 # 1.执行login函数,并将 @login 下面的 函数 作为login函数的参数,即:@login 等价于 login(movie)
    29 # 2.•将执行完的 login 函数返回值赋值给@login下面的函数的函数名
    30 @login
    31 @member
    32 def movie(name,passwd):
    33     print("welcome [%s] [%s] to movie...." % (name,passwd))
    34 
    35 @member
    36 @login
    37 def music(name):
    38     print("welcome [%s] to music..." % name)
    39 
    40 movie('huhuan','123')
    41 music('huhuan')
    42 home()

    装饰器中带有参数:

     1 # 认证函数
     2 def  auth(request,kargs):
     3     print("认证成功!")
     4 # 日志函数
     5 def log(request,kargs):
     6     print("日志添加成功")
     7 # 装饰器函数。接收两个参数,这两个参数应该是某个函数的名字。
     8 def Filter(auth_func,log_func):
     9     # 第一层封装,f1函数实际上被传递给了main_fuc这个参数
    10     def outer(main_func):
    11         # 第二层封装,auth和log函数的参数值被传递到了这里
    12         def wrapper(request,kargs):
    13             # 下面代码的判断逻辑不重要,重要的是参数的引用和返回值
    14             before_result = auth(request,kargs)
    15             if(before_result != None):
    16                 return before_result;
    17 
    18             main_result = main_func(request,kargs)   #需要装饰的函数
    19             if(main_result != None):
    20                 return main_result;
    21 
    22             after_result = log(request,kargs)
    23             if(after_result != None):
    24                 return after_result;
    25 
    26         return wrapper
    27     return outer
    28 # 注意了,这里的装饰器函数有参数,它的意思是先执行filter函数
    29 # 然后将filter函数的返回值作为装饰器函数的名字返回到这里,所以,
    30 # 其实这里,Filter(auth,log) = outer , @Filter(auth,log) =  @outer
    31 @Filter(auth,log)
    32 def f1(name,age):
    33 
    34     print("%s 正在连接业务部门1数据接口......"%name)
    35 
    36 # 调用方法
    37 f1("jack",18)
    38 
    39 结果:
    40 认证成功!
    41 jack 正在连接业务部门1数据接口......
    42 日志添加成功
  • 相关阅读:
    SpringIoC和SpringMVC的快速入门
    Swoole引擎原理的快速入门干货
    Windowns 10打开此电脑缓慢问题的一种解决办法
    CentOS下使用Postfix + Dovecot + Dnsmasq搭建极简局域网邮件系统
    CentOS7.2 创建本地YUM源和局域网YUM源
    CentOS 7.2 安装配置Samba服务器
    Zookeeper 日志输出到指定文件夹
    MySQL索引优化-from 高性能MYSQL
    Transaction事务注解和DynamicDataSource动态数据源切换问题解决
    Redis使用经验之谈
  • 原文地址:https://www.cnblogs.com/huan-ge/p/6763334.html
Copyright © 2011-2022 走看看