day4-装饰器

一 概述

装饰器:本质是函数

功能:用来装饰其他函数,为其他函数添加附加功能

二 装饰器原则

不能修改被装饰函数的源代码

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

三 实现装饰器的知识储备

函数即“变量”

高阶函数

嵌套函数

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

1. 高阶函数

实现高阶函数的两个条件:

把一个函数名当作实参传给另一个函数

返回值中包含函数名

条件1作用:在不修改被装饰函数源代码的情况下为其添加功能

import time

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

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

#没有修改bar的源代码
test(bar)  #把bar函数名当作实参传到test中

#输出
<function bar at 0x033AD6A8>
in the bar
the func run the is 1.0007984638214111

没有修改bar函数的源代码,但是调用方式改变了

条件2作用:不修改函数的调用方式

import time

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

def test(func):
    print(func)
    start_time = time.time()
   func() stop_time = time.time() print("the func run the is %s " % (stop_time-start_time)) return func #返回函数内存地址 bar = test(bar) bar() #没有改变bar函数调用方式 #输出 <function bar at 0x027FD6A8>
in the bar the func run the is 0.0 in the bar

没有修改bar函数的调用方式和源代码,但是输出结果改变了

2. 嵌套函数

定义:在一个函数的函数体内用def 去声明一个函数,而不是去调用其他函数,称为嵌套函数

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

foo()

#输出
in the foo
in the bar

四 装饰器定义

1. 定义

装饰器实现的条件:高阶函数+嵌套函数 =》装饰器

import time
#定义装饰器
def timmer(func):
    def deco():
        stat_time = time.time()
        func()
        stop_time = time.time()
        print("the func run time is %s" % (stop_time-stat_time))

    return deco

#装饰test函数
@timmer  #@timmer相当于test = timmer(test)
def test():
    time.sleep(1)
    print("in the test")

test()

#输出
in the test
the func run time is 1.0006682872772217

 执行步骤:

1.执行timmer函数,timmer(test)返回值赋值给test变量,即test = timmer(test)

2.此时的test的值是执行timmer函数返回值deco,即test = deco

3. 所以执行test,其实就是执行的是deco函数,test()就是执行deco函数

 

2. 执行函数带参数

import time
#定义装饰器
def timmer(func):
    def deco(*args,**kwargs):  #传入非固定参数
        stat_time = time.time()
        func(*args,**kwargs)  #传入非固定参数
        stop_time = time.time()
        print("the func run time is %s" % (stop_time-stat_time))

    return deco

#装饰test函数
@timmer  #@timmer相当于test = timmer(test)
def test(name,age):  #带参数
    time.sleep(1)
    print("name: %s, age:%d" % (name,age))

@timmer
def test1():  #不带参数
    time.sleep(1)
    print("in the test1")

test("alex",22)
test1()

#输出
name: alex, age:22
the func run time is 1.0008456707000732
in the test1
the func run time is 1.0008673667907715

 3.执行函数有返回值

def timmer(func):  #func = test
    def deco(*args,**kwargs):
        res = func(*args,**kwargs)  #函数执行结果返回值赋给res
        return res  #返回res
    return deco

@timmer
def test():
    print("in the test")
    return "from the test"  #执行函数rest有返回值

res = test()
print(res)

#输出
in the test
from the test

4. 装饰器带参数

之前我们的装饰器都是没有带参数的,其实我们已经能解决90%的问题了,但是如果说有一种情况:就是在你访问不同页面时,你用的验证的方式来源不同,这时就要用到带参数的装饰器了。

user,passwd = "alex","abc123"

def auth(auth_type): #传递装饰器的参数
    print("auth func:",auth_type)
    def out_wrapper(func):  #将被装饰的函数当作实参传递进来
        def wrapper(*args,**kwargs):  #将被装饰的函数的参数传递进来
            #print("wrapper func args:",*args,**kwargs)
            username = input("username:").strip()
            password = input("password:").strip()
            if auth_type == "local":
                if user == username and passwd == password:
                    print("\033[31;1mUser has passed authentication\033[0m")
                    res = func(*args,**kwargs)
                    return res
                else:
                    exit("Invalid username or password")
            elif auth_type == "ldap":
                pass
        return wrapper
    return out_wrapper

def 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 bbs():
    print("welcome to bbs page")

index()
print(home())
bbs()

 从上面的例子可以看出,执行步骤:

1. out_wrapper = auth(auth_type="local")

2. home = out_wrapper(home)

3. home()

所以这个函数的作用分别是:

1. auth(auth_type) 传递装饰器参数

2. out_wrapper(func) 把函数当作实参传递进来

3. wrapper(*args,**kwargs) 真正执行装饰的函数

 

转载于:https://www.cnblogs.com/Easonlou/p/8334778.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值