博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【24】Python装饰器笔记
阅读量:6652 次
发布时间:2019-06-25

本文共 3982 字,大约阅读时间需要 13 分钟。

装饰器

定义:本职是函数,(装饰其他函数)就是为其他函数添加附加功能。
原则:
1.不能修改被装饰的函数的源代码
2.不能修改被装饰函数的调用的方式

先来一个直观感受import timedef timmer(func): ##    def warpper(*args,**kwargs):        start_time=time.time()        func()  ##run  test1()        stop_time=time.time()        print("the func time is %s"%(start_time-stop_time))    return warpper@timmer  #@加函数名,即可调用函数def test1():  ###源代码    time.sleep(3)    print("in the test1")test1()

实现装饰器的知识储备:

1.函数即"变量"
2.高阶函数
3.嵌套函数(函数里面def声明一个函数叫嵌套函数,调用函数不叫嵌套)

下面进行一波实验:如下三种结果(验证1.函数即“变量”)A.输出报错没有bar函数def foo():    print("in the foo")    bar()foo()B.成功def bar():    print("in the bar")def foo():    print("in the foo")    bar()foo()C.输出报错,没找到定义的bar函数def foo():    print("in the foo")    bar()foo()def bar():    print("in the bar")

在将函数即“变量”的时候,先讲下python内存存储变量的机制。

当设定一个变量x=1时,内存看成一个大house,这时候大house会腾出一个房间将变量值1放入这个房间,并贴上x的门牌号。
如果是x=1,y=x,那就是变量值1这个房间将会有两个门牌号,即x&y。如图所示:
而在python内存的回收机制中,当你的房间没有门牌号时,它就会默认回收。这样可以节约空间。而当两个或多个变量值都一样时,它不会给你创建N个房间,而是同一个房间内贴上N个门牌号。
【24】Python装饰器笔记
凡是也有例外,有人就会说了,那就不会有没有变量名的变量了吗?这个在python中,还真有即匿名函数lambda。当lambda x:x*3,结果是占用的内存地址。

这里的

print(“in the poo”)
bar()
就是函数体相当于变量存放在内存中。poo()就是门牌号,当执行A时之所以会报错,就是因为没有找到bar的函数体。而C虽然定义了bar()但是定义的位置不对,函数都是从上往下读取,当执行poo()之前并没有定义,所以会报错找不到bar
【24】Python装饰器笔记

2.高阶函数(又分以下两种)

a:把一个函数名当做实参传递给另外一个函数import timedef bar():    time.sleep(3)    print("in the bar")def test1(func):  ##根据test1(bar)的调用可以看出,这里的func = bar。这就是把bar函数名传递给func当test1的实参    start_time=time.time()    func() #run bar()    stop_time=time.time()    print("the func run time is %s"%(stop_time-start_time))test1(bar)b:返回值中包含函数名import timedef bar():    time.sleep(3)    print("in the bar")def test2(func):    print(func)    return func  #f返回bar的内存值print(test2(bar))t=test2(bar) #test2执行结果赋值给了t,相当于把bar(赋值给了t,当使用t()时,就是在执行bar函数t()  #run bar()

3.嵌套函数 (在一个函数体内用def声明一个函数叫嵌套。调用不叫嵌套)

#局部即变量def foo():    def bar():        print("in the bar")    bar() ##想要输出print结果就需要一层层的调用foo()#局部作用和全局作用域的访问顺序x=0def boo():    def daa():        x=2        def son():            x=3            print(x)        son()    daa()boo()猜测下这里的输出结果是:

下面写个简单的装饰器。(高阶函数+嵌套函数=》装饰器)

不设定函数实参

import timedef timer(func):  ##func=test1=test2    def deco():        start_time=time.time()        func()  ##func=test1 =test2        stop_time=time.time()        print("the funce run time is %s" %(stop_time-start_time))    return decodef test1():    time.sleep(3)    print("in the test1")@timerdef test2():    time.sleep(3)    print("in the test2")test1=timer(test1)test1() ##-->decotest2()

当设定test实参时,可以这样写。deco() func()里面都直接*args,***kwargs不限量。如果具体某一个参数,那就可以修改为具体的。

import timedef timer(func):    def deco(*args,**kwargs):        start_time=time.time()        func(*args,**kwargs)        stop_time=time.time()        print("the funce run time is %s" %(stop_time-start_time))    return decodef test1():    time.sleep(3)    print("in the test1")@timer #非固定参数namedef test2(name):    time.sleep(3)    print("in the test2",name)test1=timer(test1)test1() ##-->decotest2("alex")

模拟远端登录与本地登录试验:

user,passwd="alex","abc"def auth(auth_type):    print("auth>>>",auth_type)    def outer_wrapper(func):        def wrapper(*args,**kwargs):            print("*args,**kwargs",*args,**kwargs)            if auth_type=="local":                username=input("Input user: ").strip()                password=input("Input password: ").strip()                if username==user and password==passwd:                    print("\033[32;1mUser has passed authentication\033[0m")                    res=func(*args,**kwargs)                    return res                else:                    exit("\033[31;1mIminvalid username or password\033[0m")            elif auth_type=="ldap":                print("不会")        return wrapper    return outer_wrapperdef index():    print("welcome to index page")@auth(auth_type="local")  ##本地验证登录def home():    print("welcome to home page")    return  "from home"@auth(auth_type="ldap")  ##远端验证登录def dds():    print("welcome to dds page")index()print(home())dds()

转载于:https://blog.51cto.com/000011211684/2068714

你可能感兴趣的文章
技术分享连载(九十六)
查看>>
RHCE 学习笔记(29) IPv6
查看>>
vsftpd+mysql+apache实现给虚拟用户分配不同目录及权限并实现远程管理
查看>>
Linux中使用crontab命令启用自定义定时任务
查看>>
BOX-虚拟桌面(MCS、PVS、Composer区别)
查看>>
设计模式之11个行为型模式
查看>>
在Digital Ocean上的MongoDB
查看>>
用oracle的java存储过程实现BLOB字段的字符串读取
查看>>
Graph Search就是语义搜索
查看>>
Java网络编程从入门到精通(3):为什么不能直接通过IP访问网站
查看>>
三层结构之联接查询的实现
查看>>
flash与中文输入法冲突,div遮挡flash问题
查看>>
配置高可用的Hadoop平台
查看>>
ActiveMQ 即时通讯服务 浅析
查看>>
关于使用C#画函数图形的问题
查看>>
MEF 打造的插件系统
查看>>
人机交互,来和我猜拳吧!
查看>>
Android -- Activity的销毁和重建
查看>>
朴素UNIX它-Linux CFS注视
查看>>
为GridView添加两种自定义分页样式
查看>>