python中的装饰器、生成器与迭代器介绍

零下一度
发布: 2017-07-18 15:25:45
原创
1611人浏览过

装饰器()

1、装饰器:本质是函数;

装饰器(装饰其他函数),就是为其他函数添加附加功能;

原则:1.不能修改被装饰函数的源代码;

   2.不能修改被装饰的函数的调用方式;

立即学习Python免费学习笔记(深入)”;

装饰器对被装饰的函数完全透明的,没有修改被装饰函数的代码和调用方式。

实现装饰器知识储备:

1.函数即“变量”;

2.高阶函数;

3.嵌套函数

高阶函数+嵌套函数=》装饰器

匿名函数(lambda表达式)

>>> calc = lambda x:x*3
>>> calc(2)
6

高阶函数:

  a.把一个函数名当做实参传递给另外一个函数;

>>> def bar():  print("in the bar.....")  
>>> def foo(func):
   print(func)>>> foo(bar)
<function bar at 0x7f8b3653cbf8>  
登录后复制


  b.返回值中包含函数名;

>>> import time
>>> def foo():  time.sleep(3)  print("in the foo.....")>>> def main(func):   print(func)   return func>>> t = main(foo)<function foo at 0x7fb7dc9e3378>>>> t()in the foo.....
登录后复制

在不修改源代码的情况下,统计程序运行的时间:

 

<span style="font-size: 16px">import time</span><br/><br/><span style="font-size: 16px">def timmer(func):</span><br/><span style="font-size: 16px">    def warpper(*args,**kwargs):   #warpper(*args,**kwargs)万能参数,可以指定参数,也可以不指定参数</span><br/><span style="font-size: 16px">        start_time = time.time()     #计算时间</span><br/><span style="font-size: 16px">        func()</span><br/><span style="font-size: 16px">        stop_time = time.time()</span><br/><span style="font-size: 16px">        print("the func run time is %s" %(stop_time-start_time)) #计算函数的运行时间</span><br/><span style="font-size: 16px">    return warpper</span><br/><br/><span style="font-size: 16px">@timmer    #等价于test1 = timmer(test1),因此函数的执行调用是在装饰器里面执行调用的</span><br/><span style="font-size: 16px">def test1():</span><br/><span style="font-size: 16px">    time.sleep(3)</span><br/><span style="font-size: 16px">    print("in the test1")</span><br/><br/><span style="font-size: 16px">test1()<br/>运行结果如下:<br/></span>
登录后复制

in the test1
the func run time is 3.001983404159546

装饰器带参数的情况:

 

<span style="font-size: 16px; font-family: 宋体">import time</span><br/><br/><span style="font-size: 16px; font-family: 宋体">def timmer(func):</span><br/><span style="font-size: 16px; font-family: 宋体">    def warpper(*args,**kwargs):</span><br/><span style="font-size: 16px; font-family: 宋体">        start_time = time.time()     #计算时间</span><br/><span style="font-size: 16px; font-family: 宋体">        func(*args,**kwargs)  #执行函数,装饰器参数情况</span><br/><span style="font-size: 16px; font-family: 宋体">        stop_time = time.time()</span><br/><span style="font-size: 16px; font-family: 宋体">        print("the func run time is %s" %(stop_time-start_time)) #计算函数的运行时间</span><br/><span style="font-size: 16px; font-family: 宋体">    return warpper    #返回内层函数名</span><br/><br/><span style="font-size: 16px; font-family: 宋体">@timmer</span><br/><span style="font-size: 16px; font-family: 宋体">def test1():</span><br/><span style="font-size: 16px; font-family: 宋体">    time.sleep(3)</span><br/><span style="font-size: 16px; font-family: 宋体">    print("in the test1")</span><br/><br/><span style="font-size: 16px; font-family: 宋体">@timmer    #test2 = timmer(test2)</span><br/><span style="font-size: 16px; font-family: 宋体">def test2(name):</span><br/><span style="font-size: 16px; font-family: 宋体">    print("in the test2 %s" %name)</span><br/><br/><span style="font-size: 16px; font-family: 宋体">test1()</span><br/><span style="font-size: 16px; font-family: 宋体">test2("alex")<br/>运行结果如下:<br/></span>
登录后复制

in the test1
the func run time is 3.0032410621643066
in the test2 alex
the func run time is 2.3603439331054688e-05

装饰器返回值情况:

 

import time
user,passwd = "alex","abc123"def auth(func):
    def wrapper(*args,**kwargs):
        username = input("Username:").strip()
        password = input("Password:").strip()if user == username and passwd == password:
            print("\033[32;1mUser has passed authentication.\033[0m")return func(*args,**kwargs)   #实际上执行调用的函数   
            # res = func(*args,**kwargs)
            # return res   #函数返回值的情况,因为装饰器调用的时候是在装饰器调用的函数,因此返回值也在这个函数中else:
            exit("\033[31;1mInvalid username or password.\033[0m")return wrapper


def index():
    print("welcome to index page...")

@auth
def home():
    #用户自己页面
    print("welcome to home page...")return "form home..."@auth
def bbs():
    print("welcome to bbs page")

index()
print(home())
bbs()
登录后复制

 

装饰器带参数的情况:

实现:1、本地验证;2、远程验证

import time
user,passwd = "alex","abc123"def auth(auth_type):'''函数的多层嵌套,先执行外层函数'''print("auth_type",auth_type)
    def out_wrapper(func):
        def wrapper(*args,**kwargs):
            print("wrapper func args:",*args,**kwargs)if auth_type == "local":
                username = input("Username:").strip()
                password = input("Password:").strip()if user == username and passwd == password:
                    print("\033[32;1mUser has passed authentication.\033[0m")
                    func(*args,**kwargs)   #实际上执行调用的函数
                    # res = func(*args,**kwargs)
                    # return res   #函数返回值的情况,因为装饰器调用的时候是在装饰器调用的函数,因此返回值也在这个函数中else:
                    exit("\033[31;1mInvalid username or password.\033[0m")
            elif auth_type == "ldap":
                print("搞毛线lbap,傻逼....")return wrapperreturn out_wrapper


def index():
    print("welcome to index page...")

@auth(auth_type="local")
def home():
    #用户自己页面
    print("welcome to home page...")return "form home..."@auth(auth_type="ldap")
def bbs():
    print("welcome to bbs page")

index()
home()
bbs()   #函数没有,因为没有调用函数,函数的调用在装饰器里面,是装饰器调用了函数
登录后复制

   迭代器和生成器

  生成器

  通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

  所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

  >>> l1 = (i for i in range(10))
  >>> l1
   at 0x7f6a9fbcaeb8>
  >>> l1.__next__()
  0
  >>> l1.__next__()
  1
  生成器:只有在调用时才会生成相应的数据;

  只有通过__next__()方法进行执行,这种能够记录程序运行的状态,yield用来生成迭代器函数。(只能往后调用,不能向前或者往后推移,只记住当前状态,因此银行的系统用来记录的时候可以使用yield函数)。

 %=  %= consumer(= consumer( i  range(,)

运行如下:
A准备吃包子了......
B准备吃包子了......
包子1被A吃了......
包子1被B吃了......
包子2被A吃了......
包子2被B吃了......
包子3被A吃了......
包子3被B吃了......
包子4被A吃了......
包子4被B吃了......
包子5被A吃了......
包子5被B吃了......
包子6被A吃了......
包子6被B吃了......
包子7被A吃了......
包子7被B吃了......
包子8被A吃了......
包子8被B吃了......
包子9被A吃了......
包子9被B吃了.....
登录后复制

  迭代器

  我们已经知道,可以直接作用于for循环的数据类型有以下几种:

  一类是集合数据类型,如list、tuple、dict、set、str等;

  一类是generator,包括生成器和带yield的generator function。

  这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。

  可以使用isinstance()判断一个对象是否是Iterable对象

>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False
登录后复制

以上就是python中的装饰器、生成器与迭代器介绍的详细内容,更多请关注php中文网其它相关文章!

python速学教程(入门到精通)
python速学教程(入门到精通)

python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
相关标签:
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号