当前位置: 移动技术网 > IT编程>脚本编程>Python > 攻克python3-装饰器

攻克python3-装饰器

2018年04月25日  | 移动技术网IT编程  | 我要评论

110接警员,武德奉文思,玮铭兄弟

装饰器

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)

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

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()

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

c.嵌套函数

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

foo()

5.写装饰器

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

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

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

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

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()

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")

以上代码中,装饰器的功能是为两个函数增加计时功能,与之前有所不同的是,原函数中是带参数和返回值,那么我们可以使用*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。

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网