python装饰器学后小记

一. 概念

这两天在学装饰器,概念简单说一下

装饰器:
    - 定义:是一个函数,用来装饰另一个函数,给其附加新的功能
    - 特点:1.不修改被装饰函数 2.不修改被装饰函数的调用方式 3.不修改被装饰函数的返回值
    - 实现:高阶函数 + 嵌套函数

1.函数(名)即'变量'
2.高阶函数:
    - 把一个函数名当做实参传个另一个函数
    - 返回值包含函数名
3.嵌套函数

二. 几个小demo

  1.给login增加一个运行时间的功能,首先把login这个函数名当做参数传给test1,此时可以把函数名'login'看做一个整体(函数体)保存在内存中,它的地址是 0x00000294C6CED0D0,当test1函数在调用func时,会运行这一段代码,我们来看装饰器的定义:test1 是一个函数√ ,给login增加了新功能(run time) √

对照装饰器的特点:1.不修改被装饰函数(login)的代码 √ 2.不修改被装饰函数的调用方式×,我们现在调用的是test1()函数 3.不修改被装饰函数的返回值 ? 这里login暂时没有返回值...

显然这不是一个装饰器

(PS:如果在生产环境中,修改了这个调用方式,麻溜收拾东西滚蛋.)

__author__ = 'tjt'
# 给登录模块增加一个程序运行时间的功能
import time


# 运行时间
def test1(func):
    print(func)  # <function login at 0x00000294C6CED0D0>
    start_time = time.time()
    func()
    stop_time = time.time()
    print("run time is ", stop_time-start_time)
    
    
# 登录模块
def login():
    print("logging...")
    time.sleep(3)
    print("success")
    
    
test1(login) 

-------结果---------
<function login at 0x00000294C6CED0D0>
logging...
success
run time is  3.0100364685058594

2.再来看第2个demo

此时,没有修改被装饰函数login代码,(貌似)也没有修改它的调用方式,是不是就可以认为test1就是一个装饰器了呢?显然,还不行,因为你需要用同名函数来接收test1的返回值,

__author__ = 'tjt'
# 给登录模块增加一个程序运行时间的功能
import time


# 运行时间
def test1(func):
    def wrapper():  # 加一层函数
        # print(func)  # <function login at 0x00000294C6CED0D0>
        start_time = time.time()
        func()
        stop_time = time.time()
        print("run time is ", stop_time-start_time)
    return wrapper  # 现在,我们给test1加一个返回值


# 登录模块
def login():
    print("logging...")
    time.sleep(3)
    print("success")


# 我们用一个与login()函数的同名变量来接收test1()的返回值
login = test1(login)
# 此时login保存的是wrapper函数的函数体,即在内存中保存的地址
# 我们再调用login()这个方法
# 没修改login源代码,增加了新的功能,貌似也没有修改调用方式
login()


--------结果---------
logging...
success
run time is  3.0090436935424805

3.第3个demo

现在,有3个页面:index页面,home页面,blog页面

需求,进入index不需要登录,进入home和blog页面需要验证登录

(再增加一个登录状态的判断,就可以登录一次,后面只要判断状态就可以了,不必重复登录)

# author tjt
# 初始化一个用户
username, password = "tjt", "abc123"

# 这里又新嵌套了一层函数,此时参数变成了验证方式'func_type'
def test1(func_type):
    # 之前传入的函数名'func'下移到这一层
    def outer_wrapper(func):
        def wrapper(*args, **kwargs):
            # 登录输入
            username1 = input("Username: ").strip()
            password1 = input("Password: ").strip()
            # 判定验证方式,本地文件验证
            if func_type == "file":
                # 验证
                if username1 == username and password1 == password:
                    print("login success")
                    # res用来接收被装饰函数的返回值
                    res = func(*args, **kwargs)
                    return res # 返回这个值,不会更改被装饰函数的返回值
                else:
                    exit("incorrect username or password")
            elif func_type == "ldap": # 远端服务器验证
                # 成功
                return True 
        return wrapper
    return outer_wrapper


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


# 增加了参数,这里参数是验证方式
@test1(func_type="file")
def home():
    print("in the home")
    return "home page"


@test1(func_type="ldap")
def blog():
    print("in the blog")
    return "blog page"


index()
print(home())
print(blog())

三.总结

一开始也说过了,这里再唠叨一下,

装饰器贯穿1个思想,3个原则:

1个思想,函数(名)即'变量':把函数名当做变量传参到装饰器函数,实际上是把'函数体'所在的内存地址传进了装饰器函数

3个原则,1.不修改被装饰函数 2.不修改被装饰函数的调用方式 3.不修改被装饰函数的返回值

刚学习装饰器,讲得不对的地方欢迎指正,一起进步!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值