python基础之装饰器详解

一、前言

装饰器:本质就是函数,功能是为其他函数添加附加功能

原则:

  • 1、不修改被修饰函数的源代码
  • 2、不修改被修饰函数的调用方式

装饰器 = 高阶函数 + 函数嵌套 + 闭包

二、高阶函数

高阶函数定义:

  • 1、函数接收的参数是一个函数
  • 2、函数的返回值是一个函数名
  • 3、满足上述条件任意一个,都可以称为高阶函数

test 函数是高阶函数,接受了一个foo 作为参数

import time
def foo():
    time.sleep(3)
    print("sleep 3s")

def test(func):
    start_time = time.time()
    func()
    stop_time = time.time()
    print("函数的运行时间是: %s" % (stop_time - start_time))

test(foo)

timer 是一个高阶函数,这个函数返回值是一个函数

import time
def foo():
    time.sleep(3)
    print("sleep 3s")

def timer(func):
    start_time = time.time()
    func()
    stop_time = time.time()
    print("执行时间{}".format(stop_time - start_time))
    return func
foo = timer(foo)
foo()
# 结果: 多运行了一次

三、函数嵌套

在函数里面定义函数,变量的作用域和生存周期不变。

def father(name):
    print("father name: %s" % name)
    def son():
        print("son name: %s" % name)
    son()
father("xu1")

# 结果:
#     father name: xu1
#     son name: xu1

四、装饰器

实现一个计算函数执行时间的函数作为装饰器,用来计算被装饰函数的执行时间并打印

import time

def timer(func):  # 实现一个计算函数执行时间的函数作为装饰器,用来计算被装饰函数的执行时间并打出
    def wrapper():
        start_time = time.time()
        func()
        stop_time = time.time()
        print("运行时间: %s" % (stop_time - start_time))
    return wrapper

# def test():  # 不使用装饰器的同等实现
#     time.sleep(3)
#     print("test sleep 3s")
#
# test = timer(test)  # 返回的是 wrapper 的地址
# test()  # 执行的是 wrapper

@timer
def test():  # 装饰器的实现
    time.sleep(3)
    print("test sleep 3s")

test()  # 执行的是 wrapper
# 结果:
#     test sleep 3s
#     运行时间: 3.000915050506592

4.1 被装饰方法带返回值

import time

def timer(func):
    def wrapper():
        start_time = time.time()
        res = func()  # 执行被装饰方法
        stop_time = time.time()
        print("运行时间: %s" % (stop_time - start_time))
        return res  # 接受正在调用的方法的返回值,并返回
    return wrapper

@timer
def test():
    time.sleep(3)
    print("test sleep 3s")
    return "test return ok"

print(test())  # 执行的是 wrapper
# 结果:
#     test sleep 3s
#     运行时间: 3.0002923011779785
#     test return ok

4.2 被装饰方法带参数

import time

def timer(func):
    """
        *args:将被修饰方法传入的非关键字参数打包为元组 args
        **kwargs: 将被修饰方法传入的关键字参数打包为字典 kwargs
    """
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)  # *args 拆解元组,按顺序传给被修饰函数; **kwargs:拆解字典
        stop_time = time.time()
        print("运行时间: %s" % (stop_time - start_time))
        return res
    return wrapper

@timer  # 给test 方法添加计算执行时间的装饰器
def test(name, age):
    time.sleep(3)
    print("name = {}, age = {}".format(name, age))
    return "test return ok"

# 调用被装饰器装饰的方法
print(test("xu", 100))  # 执行的是 wrapper
# 结果:
#     name = xu, age = 100
#     运行时间: 3.000420331954956
#     test return ok

4.3 验证功能装饰器

假如 index() 、home()、shopping_car() 三个方法都需要登录后才能访问(无法访问时里面不输入对应内容),正常情况下只需登录一次,后面访问其他方法就无需再次登录。

可以通过@auth_fun装饰器进行验证用户是否登录,如果没有就让用户输入账号密码,用户账号密码正确的记录当前登录的用户,其他方法无需再次登录。

# 用户列表
user_list = [
    {'name': 'xu1', 'passwd': '123'},
    {'name': 'xu2', 'passwd': '123'},
    {'name': 'xu3', 'passwd': '123'},
    {'name': 'xu4', 'passwd': '123'},
]
# 当前登录的用户
current_dic = {"username": None, "login": False}

# 验证用户是否登录的装饰器
#   如果用户没有登录,让用户输入账号密码,校验通过记录用户状态
def auth_fun(func):
    def wrapper(*args, **kwargs):
        if current_dic["username"] and current_dic['login']:
            res = func(*args, **kwargs)
            return res
        username = input("请输入用户名:")
        pw = input("请输入密码:")
        for u in user_list:
            if u["name"] == username and u["passwd"] == pw:
                current_dic["username"] = username
                current_dic["login"] = True
                res = func(*args, **kwargs)
                return res
        else:
            print("用户没有注册!")
    return wrapper

@auth_fun
def index():
    print("this is index")

@auth_fun
def home():
    print("this is home page")

@auth_fun
def shopping_car():
    print("this is shopping car")

index()  # 输入用户密码
home()  # index 已经登录,无需在输入
shopping_car()  # index 已经登录,无需在输入
# 结果:
#     请输入用户名:xu1
#     请输入密码:123
#     this is index
#     this is home page
#     this is shopping car

4.4 验证功能装饰器——带参数

装饰器带参数,最简单的操作就是可以对被装饰的函数进行区别处理。

# 用户列表
user_list = [
    {'name': 'xu1', 'passwd': '123'},
    {'name': 'xu2', 'passwd': '123'},
    {'name': 'xu3', 'passwd': '123'},
    {'name': 'xu4', 'passwd': '123'},
]
# 当前登录的用户
current_dic = {"username": None, "login": False}

"""
    注意:带参数的装饰器会比没有带参数的装饰器多嵌套一层函数(多了auth)
        调用方式是 @auth(auth_type="type1"), 返回 auth_fun,
        也就是说 @auth(auth_type="type1")相当于 @auth_fun
        但是 auth_fun 函数所在的嵌套作用域多了一个 auth_type 的变量
"""
def auth(auth_type="type1"):
    def auth_fun(func):
        def wrapper(*args, **kwargs):
            if auth_type == "type1":
                if current_dic["username"] and current_dic['login']:
                    res = func(*args, **kwargs)
                    return res
                username = input("请输入用户名:")
                pw = input("请输入密码:")
                for u in user_list:
                    if u["name"] == username and u["passwd"] == pw:
                        current_dic["username"] = username
                        current_dic["login"] = True
                        res = func(*args, **kwargs)
                        return res
                else:
                    print("用户没有注册!")
            elif auth_type == "type2":
                print("不用授权直接登录: type = {}".format(auth_type))
                res = func(*args, **kwargs)
                return res
            else:
                print("其他type没有实现")
        return wrapper
    return auth_fun

"""
    auth_fun = @auth(auth_type="type1")
    auth_fun 所在的嵌套与将有一个 auth_type 变量
    然后通过 @auth()方法返回的对象注解 index,相当于 @auth_fun 注解index 方法,最后得到 wrapper 对象
"""
@auth(auth_type="type1")
def index():
    print("this is index")

@auth(auth_type="type2")
def home():
    print("this is home page")

@auth(auth_type="type3")
def shopping_car():
    print("this is shopping car")

home()  # 注意:auth_type="type2",这个方法无需登录可以直接执行
index()  # 注意:auth_type="type1",需要登录
shopping_car()  # 注意:auth_type="type3",没有做处理
# 结果:
#     不用授权直接登录: type = type2
#     this is home page
#     请输入用户名:xu1
#     请输入密码:123
#     this is index
#     其他type没有实现

到此这篇关于python基础之装饰器详解的文章就介绍到这了,更多相关python装饰器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python 装饰器的基本使用

    知识点 简单的装饰器 带有参数的装饰器 带有自定义参数的装饰器 类装饰器 装饰器嵌套 @functools.wrap装饰器使用 基础使用 简单的装饰器 def my_decorator(func): def wrapper(): print('wrapper of decorator') func() return wrapper() def test(): print('test done.') test = my_decorator(test) test 输出: wrapper of dec

  • python装饰器代码深入讲解

    python装饰器就是用于扩展原函数功能的一种函数,这个函数特殊的地方就是它的返回值也是一个函数,使用Python装饰器的一个好处就是:在不需要修改原函数代码的情况下,给函数增加新的功能. 先来看个例子: def say(): print('Nice day') say() # 这个函数的输出为: Nice day 现在,我想在输出Nice day的前面再打印一行****************,类似下面的效果: **************** Nice day 一般情况下,我可以修改上面的代

  • Python 的lru_cache装饰器使用简介

    Python 的 lru_cache 装饰器是一个为自定义函数提供缓存功能的装饰器.其内部会在下次以相同参数调用该自定义函数时直接返回计算好的结果.通过缓存计算结果可以很好地提升性能. 1 从示例说起 假设我们有一个计算斐波那契数列的求和函数,其内部采用递归方式实现. from xxx.clock_decorator import clock @clock def fibonacci(n): if n<2: return n return fibonacci(n-2)+fibonacci(n-1

  • python装饰器实现对异常代码出现进行自动监控的实现方法

    异常,不应该存在,但是我们有时候会遇到这样的情况,比如我们监控服务器的时候,每一秒去采集一次信息,那么有一秒没有采集到我们想要的信息,但是下一秒采集到了, 而后每次的采集都能采集到,就那么一次采集不到,我们应该针对这一次采集不到进行分析吗,这种的情况可以说无法重复出现,我们也无法避免,因为外界的因素太多太多,我们无法去控制这些外面的因素,所以我们会有这样的需求,一段时间内出现频率多少次,我们才能显示一次报警,或者说,一段时间内出现的频率达到我们的异常许可范围我们认为这样的属于异常,我们可以发出报

  • Python 中的函数装饰器和闭包详解

    函数装饰器可以被用于增强方法的某些行为,如果想自己实现装饰器,则必须了解闭包的概念. 装饰器的基本概念 装饰器是一个可调用对象,它的参数是另一个函数,称为被装饰函数.装饰器可以修改这个函数再将其返回,也可以将其替换为另一个函数或者可调用对象. 例如:有个名为 decorate 的装饰器: @decorate def target(): print('running target()') 上述代码的写法和以下写法的效果是一样的: def target(): print('running targe

  • python 装饰器重要在哪

    1.什么是装饰器? 要理解什么是装饰器,您首先需要熟悉Python处理函数的方式.从它的观点来看,函数和对象没有什么不同.它们有属性,可以重新分配: def func(): print('hello from func') func() > hello from func new_func = func new_func() > hello from func print(new_func.__name__) > func 此外,你还可以将它们作为参数传递给其他函数: def func(

  • Python基于staticmethod装饰器标示静态方法

    英文文档: staticmethod(function) Return a static method for function. A static method does not receive an implicit first argument. The @staticmethod form is a function decorator – see the description of function definitions in Function definitions for de

  • Python高阶函数与装饰器函数的深入讲解

    本文主要介绍的是Python高阶函数与装饰器函数的相关内容,分享给大家,下面话不多说了,来一起看看详细的介绍吧 高阶函数 1.可以使用函数对象作为参数的函数 2.或可以将函数作为返回值的函数 3.函数对象:定义好的函数,使用函数名调用(不要加括号) #将函数作为参数的高阶函数,通过传入不同的函数,可以使执行的结果不同 4.内置高阶函数 (1)map数据映射函数 map函数接收的是两个参数,一个函数,一个序列,其功能是将序列中的值处理再依次返回至列表内.其返回值为一个迭代器对象 (2)reduce

  • python基础之装饰器详解

    一.前言 装饰器:本质就是函数,功能是为其他函数添加附加功能 原则: 1.不修改被修饰函数的源代码 2.不修改被修饰函数的调用方式 装饰器 = 高阶函数 + 函数嵌套 + 闭包 二.高阶函数 高阶函数定义: 1.函数接收的参数是一个函数 2.函数的返回值是一个函数名 3.满足上述条件任意一个,都可以称为高阶函数 test 函数是高阶函数,接受了一个foo 作为参数 import time def foo(): time.sleep(3) print("sleep 3s") def te

  • python中的装饰器详解

    在了解装饰器的之前一定要先了解函数作为参数传递, 什么是函数内嵌,请参考我之前写的博客函数简介 因为在python里面,函数也是对象,也可以作为参数进行传递.python装饰器本质也是一种特殊函数,它接收的参数是函数对象,然后动态地函数参数添加额外的功能,而不用修改原有的函数对象.python装饰器传入的参数是函数,返回的值也是函数! python装饰器思想有点类似设计模式的装饰模式, 其意图是动态地给函数对象添加额外的功能.比如像增加日志打印的功能,有点面向切面编程(AOP)的感觉. 装饰器语

  • python三大器之装饰器详解

    目录 装饰器 总结 装饰器 讲装饰器之前要先了解两个概念: 对象引用 :对象名仅仅只是个绑定内存地址的变量 def func(): # 函数名仅仅只是个绑定内存地址的变量 print("i`m running") # 这是调用 func() # i`m running # 这是对象引用,引用的是内存地址 func2 = func print(func2 is func) # True # 通过引用进行调用 func2() # i`m running 闭包:定义一个函数A,然后在该函数内

  • Python学习之装饰器与类的装饰器详解

    目录 装饰器 装饰器的定义 装饰器的用法 类中的装饰器 类的装饰器-classmethod 类的装饰器-staticmethod 类的装饰器-property 通过学习装饰器可以让我们更好更灵活的使用函数,通过学会使用装饰器还可以让我们的代码更加优雅. 在我们的实际工作中,很多场景都会用到装饰器,比如记录一些日志.或者屏蔽一些不太合法的程序执行从而使我们的代码更加安全. 装饰器 什么是装饰器?虽然对这个次感到陌生,但是完全不需要担心. 首先,装饰器也是一种函数:只不过装饰器可以接收 函数 作为参

  • Python 3.7新功能之dataclass装饰器详解

    前言 Python 3.7 将于今年夏天发布,Python 3.7 中将会有许多新东西: 各种字符集的改进 对注释的推迟评估 以及对dataclass的支持 最激动人心的新功能之一是 dataclass 装饰器. 什么是 Data Class 大多数 Python 开发人员编写过很多像下面这样的类: class MyClass: def __init__(self, var_a, var_b): self.var_a = var_a self.var_b = var_b dataclass 可以

  • python高级语法之闭包和装饰器详解

    一.闭包 闭包的形成条件: 1.函数嵌套. 2.内部函数使用了外部函数的变量或者参数. 3.外部函数返回了使用外 部变量的内部函数. 二.一个简单的例子 def func_out(num1): def inner(num2): res = num1 + num2 print(res) return inner # a = func_out(10)(10) a = func_out(10) a(10) 闭包修改外部函数的变量: 在闭包内修改外部函数的变量需要使用nonlocal关键字 def fu

  • python 装饰器详解与应用范例

    什么是装饰器 从字面意思上来看,装饰器是用来装饰其他东西的工具.在python中装饰器分为函数装饰器和类装饰器. 简而言之,函数装饰器是用来装饰函数的装饰器,其主要目的是增加目标函数的功能,类装饰器也就是装饰类的装饰器,增加类的功能. 函数装饰器 装饰器本质是嵌套函数 下面是一个简单的装饰器 # fun1为装饰器名称,function指的是被装饰的函数 def fun1(function): def fun2(): print("开始了!") function() # 执行被装饰的函数

  • python中的迭代器,生成器与装饰器详解

    目录 迭代器 生成器 装饰器 总结 迭代器 每一个可迭代类内部都要实现__iter__()方法,返回一个迭代类对象,迭代类对象则定义了这个可迭代类如何迭代. for循环调用list本质上是是调用了list的迭代器进行迭代. # 对list进行for循环本质上是调用了list的迭代器 list = [1,2,3,4] # for 循环调用 for elem in list: print(elem) # 迭代器调用 list_iter = list.__iter__() while True: tr

  • Python基础之time库详解

    一.前言 time库运行访问多种类型的时钟,这些时钟用于不同的场景.本篇,将详细讲解time库的应用知识. 二.获取各种时钟 既然time库提供了多种类型的时钟.下面我们直接来获取这些时钟,对比其具体的用途.具体代码如下: import time print(time.monotonic()) print(time.monotonic_ns()) print(time.perf_counter()) print(time.perf_counter_ns()) print(time.process

  • Python基础之元类详解

    1.python 中一切皆是对象,类本身也是一个对象,当使用关键字 class 的时候,python 解释器在加载 class 的时候会创建一个对象(这里的对象指的是类而非类的实例) class Student: pass s = Student() print(type(s)) # <class '__main__.Student'> print(type(Student)) # <class 'type'> 2.什么是元类 元类是类的类,是类的模板 元类是用来控制如何创建类的,

随机推荐