Python-装饰器详解

装饰器

介绍

在Python中,装饰器是一种特殊的语法,用于修改或增强函数的功能。装饰器是Python的高级特性之一,它允许我们通过在不修改原函数代码的情况下,添加额外的功能或行为。

装饰器是一个函数,它接受一个函数作为参数,并返回一个新的函数。装饰器函数通常使用@符号放在要修饰的函数定义之前

python中的装饰器(decorator)一般采用语法糖的形式,是一种语法格式。比如:@classmethod,@staticmethod,@property,@wraps(),等都是python中的装饰器。

#装饰器: 是一种程序设计模式,主要用于给函数或者类添加一些额外的功能
#   又不希望通过继承或者修改源代码的方式去实现,那就使用装饰器

# 装饰器:不改变函数或类或者源代码的基础上,添加额外功能。
# 装饰器的本质就是闭包,它需要把一个callable对象(能够打括号调用的对象)作为参数转递进来。

使用

闭包

闭包:需要满足三个条件

  • 有内外函数
  • 外函数要返回内函数,而不是返回函数的调用结果
  • 内函数有引用外函数的变量

函数体内的局部变量,一般情况下,调用的时候生成,结束的使用释放
在闭包的条件下,局部变量不会随着调用的结束而释放

变量生命周期
局部变量 -- 函数的调用生成,函数调用完成释放
def func1():
    print("i am func1")


def outer():
    x = 30
    func1()
    print(f"x is {x}")

outer()
print(x)
def outer(x):
    a = 200
    def inner():
        print(x+a)
    return inner

d = outer(100)
#此时,d就是内函数,如果不调用d,就不会有输出
# d()
# 我们需要调用内函数才可以看到调用结果。

装饰器

看一段代码执行时间:

定义func1函数

def func1():
    time.sleep(1)
    print("i am func1")

在函数前后查看时间。

func1()

# 时间戳
start = time.time()
f = func1()
end = time.time()
print(f"执行函数花了{end-start}s")

使用装饰器查看时间

定义装饰器

def runtime(func):
    def inner(*args,**kwargs):          # *args, **kwargs  让装饰器更加通用。
        start = time.time()
        result = func(*args,**kwargs)
        end = time.time()
        print(f"函数执行花了{end-start}s")
        print(f"执行了{func.__name__}函数")
        return result                   # inner 函数返回原函数的返回值。
    return inner

定义函数

@runtime
def func2(a,b):
    time.sleep(2)
    print("i am func2")
    return a+b

func2(1,2)

注意:

  • 装饰器只能装饰函数或者类
  • 被装饰过的函数,不是原函数了,是装饰器返回的内函数
  • 添加的功能放在装饰器的内函数里面。

练习:

添加额外功能
统计运行时间
权限控制
日志记录

执行了什么函数  -- 写入日志,记录INFO 等级 ,写到文件和屏幕
计时功能装饰器
import functools
from logset import logger

def log(func):
    def inner_log(*args, **kwargs):
        logger.info(f"开始执行{func.__name__}函数")
        result = func(*args, **kwargs)
        logger.info(f"{func.__name__}函数,执行结束!")
        return result
    return inner_log

def runtime(func):
    @functools.wraps(func)
    def inner(*args,**kwargs):
        start = time.time()
        result = func(*args,**kwargs)
        end = time.time()
        print(f"函数执行花了{end-start}s")
        return result

    return inner

@log                # test_func1 = log ( runtime( test_func1() ) )
@runtime
def test_func1():
    time.sleep(1)
    print("this is func1")


test_func1()

装饰器带参数

自身不转入参数的装饰器,使用两层函数定义
自身转入参数的装饰器,使用三层函数定义

import time

user = {"root":"123456","admin":"admin123"}

def deco(username,passwd):
    def runtime(func):
        def inner(*args,**kwargs):
            if username in user and user[username] == passwd:
                if username == "root":
                    start = time.time()
                    result = func(*args,**kwargs)
                    end = time.time()
                    print(f"{func.__name__}执行花了{end-start}s")
                    return result
                else:
                    print("用户名密码不正确")
            else:
                print(f"用户:{username}没有权限")
        return inner
    return runtime

@deco(username="r",passwd="123456")
def add(a,b):
    time.sleep(1)
    return a+b

add(1,2)

类实现装饰器

import time

class A():
    def __init__(self,func):
        self.func = func

    def __call__(self, *args, **kwargs):
        start = time.time()
        result = self.func()
        end = time.time()
        print(f"{self.func.__name__}函数执行花了{end - start}s")
        return  result


@A              #   func1 = A(func1)   这是实例化
def func1():
    time.sleep(1)
    print("i am func1")


func1()

带参数的装饰器,用类实现

user = {"root":"123456","admin":"admin123"}
class A:
    def __init__(self,username,passwd):
        self.username = username
        self.passwd = passwd

    def __call__(self, func):
        def inner(*args, **kwargs):
            if self.username in user and user[self.username] == self.passwd:
                if self.username == "root":
                    start = time.time()
                    result = func(*args, **kwargs)
                    end = time.time()
                    print(f"{func.__name__}执行花了{end - start}s")
                    return result
                else:
                    print("用户名密码不正确")
            else:
                print(f"用户:{self.username}没有权限")
        return inner





@A(username = "root",passwd="123456")       #   a = A(username = "root"),func1 = a(func1)   这是实例化
def func1():
    time.sleep(1)
    print("i am func1")

func1()
  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
函数装饰器Python中一种特殊的语法,可以用来修改、扩展或包装其他函数的功能。装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数作为结果。 装饰器的语法使用了@符号,它放在要修饰的函数定义之前。当调用被修饰的函数时,实际上是调用了装饰器返回的新函数。 下面是一个简单的装饰器示例: ```python def decorator(func): def wrapper(): print("Before function execution") func() print("After function execution") return wrapper @decorator def say_hello(): print("Hello, world!") say_hello() ``` 在这个例子中,`decorator`是一个装饰器函数,它接受一个函数作为参数,并定义了一个内部函数`wrapper`来包装原始函数。`wrapper`函数在调用原始函数前后分别打印了一些信息。 通过在`say_hello`函数定义之前添加`@decorator`语法,我们将`say_hello`函数传递给`decorator`装饰器,并将返回的新函数赋值给`say_hello`。因此,当我们调用`say_hello`时,实际上是调用了被修饰后的函数`wrapper`。 这样,每次调用`say_hello`函数时,都会在执行前后打印一些信息。 装饰器可以用于很多场景,比如日志记录、性能分析、权限检查等。它们提供了一种简洁而优雅的方式来修改函数的行为,而无需修改函数本身的定义。同时,装饰器还可以堆叠使用,即一个函数可以被多个装饰器修饰。 希望这个简单的示例能够帮助你理解Python函数装饰器的基本概念和用法。如果你有更多的问题,可以继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈密猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值