Python装饰器

装饰器

装饰器本身就是一个为其他函数添加附加功能的函数

装饰器原则:
- 不修改被修饰函数的源代码
- 不修改被修饰函数的调用方式

比如要增加检测一段代码的执行时间

可以重写源代码

import time

def A():
    start = time.time()

    res = 0
    for i in l
        res += i

    end = time.time()

    print(end-start)
    return res

是可以这样写的

但是如果你有n个函数都需要 求运行时间的话
你不可能一个函数一个函数的去改

况且改源代码违反开放封闭原则

可以采用回调的方式

import time

def A():
    pass

def B():
    pass

def C():
    pass

def pack(func):
    start = time.time()
    func()
    end = time.time()
    print(end-start)

pack(A)
pack(B)
pack(C)

不过要是用回调的话,调用方式就发生变化了

多数情况下是这样
我要给线上正在运行中的代码添加一些功能
但调用方式是不变的

装饰器

装饰器 实际上就 等于
- 高阶函数
- 函数嵌套
- 闭包

import time

def outer(func):
    def inner():
        start = time.time()
        func()
        end = time.time()
        print(end-start)
    return inner

@outer
def A():
    pass

@outer
def B():
    pass

@outer
def C():
    pass


A()
B()
C()

原来的代码不动,不过每个代码都新增了检测运行时间的功能

高阶函数

高阶函数的定义
- 函数接收的参数是一个函数名
- 函数的返回值是一个函数名
- 满足上述条件任意一个,都可以称之为高阶参数

函数接收一个函数名

def A():
    pass

def pack(func):
    func()

pack(A)     # 相当于直接调用A()

函数接收一个函数名并返回函数名

def A():
    pass

def pack(func):
    return func  

pack(A)()       # pack(A) 就相当于A  再加上一个()就是调用A()

# 或者 可以 A = pack(A)
# A()

函数嵌套

在一个函数(私有作用域)中定义另一个函数

在函数中打印locals() 会返回

{'son': <function father.<locals>.son at 0x0000018DC74657B8>, 'name': 'zzz'}
可以看到了 son指向一个函数对象
name指向一个字符串对象

如果不在函数内部调用的话,就算执行外部的函数
里面的函数也不会执行

装饰器基本实现

import time


def outer(func):
    def inner():
        print('新功能1')
        func()
        print('新功能2')
    return inner
# 用到了闭包 高阶函数 以及 函数的嵌套

def t():
    time.sleep(1)
    print(123)


t = outer(t)
t()

如果这样写的话,那每给一个函数添加功能,就需要进行一次重新的赋值
这样很复杂

于是乎可以用语法糖@来解决问题

import time


def outer(func):
    def inner():
        print('新功能1')
        func()
        print('新功能2')
    return inner
# 用到了闭包 高阶函数 以及 函数的嵌套

@outer      # 就相当于 t = outer(t)
def t():
    time.sleep(1)
    print(123)


t()
  1. 如果被修饰的函数有返回值的话
import time


def outer(func):
    def inner():
        print('新功能1')
        result = func()     # 将传进来的被修饰函数的返回值赋值给一个局部变量
        print('新功能2')
        return result+'d'   # 返回处理后的返回值
    return inner
# 用到了闭包 高阶函数 以及 函数的嵌套

@outer      # 就相当于 t = outer(t)
def t():
    time.sleep(1)
    print(123)
    return 'abc'


print(t())      # 先执行t() 然后打印t()的返回值
  1. 如果被修饰的函数有形参的话
import time


def outer(func):
    def inner(*args,**kwargs):      
    # 无论被修饰的函数需要多少实参,这里都能接收到(接收到在原封不动的传给函数)

        print('新功能1')
        result = func(*args,**kwargs)     
        # 将传进来的被修饰函数的返回值赋值给一个局部变量
        # 这里不去掉*的用途的解包
        # 把传进来的元组和字典 解成 具体的参数

        print('新功能2')
        return result+'d'   # 返回处理后的返回值
    return inner
# 用到了闭包 高阶函数 以及 函数的嵌套

@outer      # 就相当于 t = outer(t)
def t(name,age):
    time.sleep(1)
    print(123)
    return 'abc'


print(t())      # 先执行t() 然后打印t()的返回值

装饰器添加验证功能

一个简单的模拟登陆验证功能

def auth_func(func):
    def wrapper(*args,**kwargs):
        username = input("请输入用户名: ").strip()
        password = input("请输入密  码: ").strip()
        if username == 'px' and password=="123":
            res = func(*args,**kwargs)
            return res
        else:
            print("用户名或密码错误")
    return wrapper

@auth_func
def index():
    print("欢迎来到主页")

登陆验证模拟session功能

user_list = [
    {'name': 'px1', 'passwd': '123'},
    {'name': 'px2', 'passwd': '123'},
    {'name': 'px3', 'passwd': '123'}
    # 假如说这是数据库中用户的信息
]

current_dic = {'username': None, 'login': False}    # 用户登录状态


def auth_func(func):
    def wrapper(*args, **kwargs):
        # 首先判断当前用户的登录状态,已经登录的话可以直接进行访问
        if current_dic['username'] and current_dic['login']:
            res = func(*args, **kwargs)
            return res

        username = input("请输入用户名: ").strip()
        password = input("请输入密  码: ").strip()
        for user_dic in user_list:

            if username == user_dic['name'] and password == user_dic['passwd']:
                # 如果登录时输入的信息在数据库中,那么就表示登录成功
                # 然后改一下 用户登录状态
                current_dic['username'] = username
                current_dic['login'] = True

                res = func(*args, **kwargs)
                return res
        else:
            print("用户名或密码错误")

    return wrapper


@auth_func
def index():
    print("欢迎来到主页")


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值