欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

攻克python3-装饰器

程序员文章站 2022-04-28 08:29:37
装饰器 1.为什么要使用装饰器? 在产品升级中,有成千上百个函数,要为这些函数增加某些功能,如果一个个函数的修改,岂不是浪费资源,浪费时间,这是装饰器的好处就展现了,它可以在短时间内完成你对许多函数的修改。 2.什么是装饰器? 装饰器也是函数,是装饰其他函数的函数(为其他函数增加功能) 3.装饰器的 ......

装饰器

1.为什么要使用装饰器?

在产品升级中,有成千上百个函数,要为这些函数增加某些功能,如果一个个函数的修改,岂不是浪费资源,浪费时间,这是装饰器的好处就展现了,它可以在短时间内完成你对许多函数的修改。

2.什么是装饰器?

装饰器也是函数,是装饰其他函数的函数(为其他函数增加功能)

3.装饰器的原则:

  a.不能修改原函数的代码

  b.不改变原函数的调用方式

4.装饰器的知识储备:

  a.函数即“变量”

  b.高阶函数

  c.嵌套函数

a.函数即“变量”

在定义函数时,系统将函数体内的函数过程作为字符串保存在内存中,当作一个变量储存,只是把地址赋给了函数名,在调用函数时,再去解释函数过程

b.高阶函数

1.一个函数的函数名作为另一个函数的参数

import time
def bar():
    time.sleep(2)
    print("in the bar")

def test1(func):
    start_time=time.time()
    func()
    stop_time=time.time()
    print("the test run time is %s"%(stop_time-start_time))


bar()
print("-----------")
test1(bar)

攻克python3-装饰器

通过上面的演示是不是得出一个结论:高阶函数可以在不改变原函数的源代码的情况下,为其增加功能,但会改变原函数的调用方式

2.一个函数的返回值包括函数名

import time
def bar():
    time.sleep(2)
    print("in the bar")


def test1(func):
    start_time=time.time()
    func()
    stop_time=time.time()
    print("the test run time is %s" % (stop_time - start_time))
    return func


bar=test1(bar)
print("------")
bar()

攻克python3-装饰器

通过上面的演示是不是得出一个结论:高阶函数可以不改变原函数的调用方式,但是没有添加新功能

c.嵌套函数

def foo():
    print("in the foo")
    def bar():
        print("in the bar")
    bar()

foo()

攻克python3-装饰器

5.写装饰器

a.装饰器是为给其他函数增加功能,但是不能改变原函数的源代码,那我们怎么才能不改变原函数的源代码,回顾上文,通过高阶函数(将函数名作为另一个函数的参数)定义一个新函数,在新函数中调用原函数,并且添加新功能,这样就可以实现我们的目标

#现在我有一个函数tets1,然后为它添加一个新功能
def dec(func):
    print("我是新功能!")
    func()

def test1():
    print("in the test1")

test1()
print("-------")
dec(test1)

攻克python3-装饰器

b.在不修改原函数的同时,而且也不能修改函数的调用方式,函数的调用方式是不是函数名(),那么函数即“变量”,在这里就起大作用了,在上面代码中,我们可以将新函数的函数地址赋给原函数的函数名,原函数的函数名对应的内存空间发生了改变,这片新的内存空间中既有原函数的功能,也有新增加的功能,那么我们通过高阶函数(返回值中包含函数名)将原函数的函数名重新赋值,这样我们的目的就达到了。

#因为需要返回新函数的函数名(函数地址),所以要使用嵌套函数
def foo(func):             #func=test1  将test1函数地址传给了func   所以新函数的内存空间保存了原函数的内存地址,可以通过调用新函数来调用原函数,并且增加功能
    def dec():
        print("我是新功能!")
        func()
    return dec

@foo    #相当于test1=foo(test1)    在python中 装饰器 用@装饰圈名 来表示
def test1():
    print("in the test1")

test1()
print("-------")
#test1=foo(test1)
test1()

攻克python3-装饰器

6.高级版装饰器

import time
def timer(func): #func=test1 将test1的地址赋给func def deco(*args,**kwargs): start_time = time.time() res=func(*args,**kwargs) #相当于调用test1 stop_time=time.time() print("the func run time is %s" % (stop_time - start_time))
     return res return deco #将deco的地址返回 @timer #相当于test1=timer(test1) def test1(): time.sleep(2) print("in the test1") @timer def test2(name): time.sleep(2) print("in the test2",name) return name # test1=timer(test1) #test1=deco 将deco的地址赋给test1 test1() #相当于调用deco test2("phk")

攻克python3-装饰器

以上代码中,装饰器的功能是为两个函数增加计时功能,与之前有所不同的是,原函数中是带参数和返回值,那么我们可以使用*args **kwargs来充当函数参数,与参数一样,我们给新函数定义返回值,这样就做到了透明化处理.

7.高潮版

user,passwd="phk","123"

def auth(auth_type):
    #print(auth_type)
    def outer(func):
        #print(func)
        def deco(*args,**kwargs):
            if auth_type == "local":
                username=input("usernane:").strip()
                password=input("password:").strip()
                if user==username and passwd==password:
                    func()
                else:
                    exit("账号密码错误")
            elif auth_type=="ldap":
                print("不会")
        return deco
    return outer

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

@auth(auth_type="local")            #相当于home=auth(auyh_type="local")(func)
def home():
    print("welcome to home page")

@auth(auth_type="ldap")
def bbs():
    print("welcome to bbs page")

index()
home()
bbs()

装饰器的功能是为三个页面函数添加登陆功能,不同的是需要选择本地登陆还是ldap登陆,说白了就是在装饰器外面在套一层函数,传进来的参数可以作为局部参数,可以咱函数体内使用,但是需要明白一点

 @auth(auth_type="local") 相当于home=auth(auyh_type="local")(func)。

 解释器会先翻译“auth(auth_type = 'local')”,再将其返回值(假设给了_func这个不存在的函数名)当作函数指针,这里的_func函数名代表的是outer,然后再去执行“func = _func(func)”,而这个func函数名代表的其实就是deco。