首页 > 编程语言 >带参数的 Python 装饰器让你的代码更优雅

带参数的 Python 装饰器让你的代码更优雅

时间:2024-11-10 21:30:21浏览次数:1  
标签:return chof Python 代码 优雅 def com 装饰 decorator

引言
在上一篇文章中,我们介绍了 Python 装饰器的基本概念及其简单用法。

前面讲到的装饰器都是不带参数的装饰器,在需要对装饰器做一些针对性的处理的时候就不太适用了,这个时候需要对装饰器传入一些参数,根据传入的参数进行不同的处理。

带参数装饰器在实际开发中能够灵活地调整函数行为,广泛应用于日志记录、权限验证和缓存等场景。。

如何定义带参数的装饰器
带参数的装饰器的结构稍微复杂一些。我们要定义一个外层函数来接收装饰器的参数,并在这个外层函数中定义实际的装饰器函数,相当于将之前的装饰器用一个正常的函数包装了一层。下面来看一下带参数的装饰器和不带参数的装饰器的对比。

不带参数的装饰器

def decorator(func):
def wrapper():
print(f"Decorator")
return func()

return wrapper

带参数的装饰器:

def decorator_with_args(arg1=None, arg2=None):
def decorator(func):
def wrapper():
print(f"Decorator arguments: {arg1}, {arg2}")
return func()

    return wrapper

return decorator

在上面带参数的装饰器中,decorator_with_args 是外层装饰器函数,它接收两个参数 arg1 和 arg2。内部的 decorator 函数是实际的装饰器,而 wrapper 函数则是用来包装被装饰的函数。

如何使用带参数的装饰器
@decorator_with_args("Hello", "World")
def greet():
print(f"Greeting name")

greet()

输出:

Decorator arguments: Hello, World
Greeting name

在这个例子中,greet 函数被 decorator_with_args 装饰,传入了两个参数。装饰器在调用 greet 函数之前,先打印了装饰器的参数。

注意:带参数的装饰器有两个可选参数,可以选择不传。但需要注意的是,@decorator_with_args() 不能简写为 @decorator_with_args,因为 decorator_with_args 本质上是一个函数,必须调用后才能生效。

两种装饰器用法区别
使用不带参数的装饰器时,用法如下,要注意区别。

def decorator(func):
def wrapper():
print(f"Decorator")
return func()

return wrapper

@decorator
def greet():
print(f"Greeting name")

greet()

处理可变参数
在很多时候,我们会遇到被装饰的函数有参数的情况,这时要怎么处理呢。

为了解决这个问题,我们可以使用 *args 和 **kwargs 来接收函数的所有参数。

装饰器处理可变参数

def func_decorator(decorator_arg):
def decorator(func):
def wrapper(args, **kwargs):
print(f"Decorator argument: {decorator_arg}")
print(f"Function arguments: {args}, {kwargs}")
return func(
args, **kwargs)

    return wrapper

return decorator

@func_decorator("Test")
def add(*args):
return sum(args)

result = add(1, 2, 3, 4)
print(f"Result: {result}")

输出:

Decorator argument: Test
Function arguments: (1, 2, 3, 4), {}
Result: 10

在这个示例中,func_decorator 装饰器可以处理在被装饰的函数有参数的情况,并且可以自适应任何参数,装饰器能够正确处理这些参数。

带参数装饰器的使用案例
自定义日志格式
在实际开发中,我们常常需要记录函数的执行日志。通过带参数的装饰器,我们可以自定义被装饰函数的参数和返回值,甚至可以做到修改被装饰函数的参数和返回值。

def log_decorator(fun_args=False, fun_result=False):
def decorator(func):
def wrapper(args, **kwargs):
if fun_args:
print(f'func args is: {args} {kwargs}')
if fun_result:
result = func(
args, **kwargs)
print(f'func result is: {result}')
return result
else:
return func(*args, **kwargs)

    return wrapper

return decorator

@log_decorator(True, True)
def multiply(x, y):
return x * y

print(f"Result: {multiply(3, 5)}")

@log_decorator(False, False)
def multiply(x, y):
return x * y

print(f"Result: {multiply(3, 5)}")

结果:

func args is: (3, 5) {}
func result is: 15
Result: 15

Result: 15

在这个示例中,log_decorator 装饰器接受两个布尔型参数,用于判断是否要输出函数参数和函数返回值。

此处日志输出比较简单,仅做为示例参考,生产环境要做一些比较复杂的判断并且要将日志持久化到磁盘的日志文件中。

缓存机制
import time
from functools import lru_cache

class Timer:
def init(self):
self.start = None

def __enter__(self):
    import time
    self.start = time.time()

def __exit__(self, type, value, traceback):
    print(f'time is:{time.time() - self.start}')

@lru_cache(maxsize=20)
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)

with Timer() as timer:
print(fibonacci(15))

with Timer() as timer2:
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(15))

chof.cdhgs.com
chof.borkjc.com
chof.huoyiyingshi.com
chof.chinachaiyao.com
chof.njhhcw.com
chof.kangshungcsl.com
chof.haixiaocdn.com
chof.jszcxny.com
chof.baiyichi.com
chof.chengducxwc.com
chof.seemlgo.com
chof.shyachao.com
chof.dhl-d.com
chof.tajqzl.com
chof.hzsunbyte.com
chof.tjzxjy.com
chof.qrpress.com
chof.zhanhao118.com
chof.marsdrinkschina.com
chof.xjlqcl.com
chof.5000news.com
chof.2500trip.com
chof.htsyfs.com
chof.hmgjjd.com
chof.tcccpsb.com
chof.hfsmttp.com
chof.nnlianbao.com
chof.xinchengabc.com
chof.njns56.com
chof.gzlcjzs.com
chof.xinlvchuang.com
chof.juanbanjicj.com
chof.tongtaijituan.com
chof.lydsmp.com
chof.shinenergygroup.com
chof.jingranchimian.com
chof.tj-shengming.com
chof.njxlkhs.com
chof.shzljr.com
chof.guanlinyouxuan.com
chof.ynyoutu.com
chof.jiadalong.com
chof.jumeizi.com
chof.zhs888.com
chof.cnaoxin.com
chof.afu365.com
chof.tzhyex.com
chof.xincaiit.com
chof.senmaohuanbao.com
chof.bjqunlemuye.com

结果:

14 13
13 12
12 11
11 10
10 9
9 8
8 7
7 6
6 5
5 4
4 3
3 2
2 1
1 0
610
time is:4.076957702636719e-05

14 13
13 12
12 11
11 10
10 9
9 8
8 7
7 6
--- 此处数据量太大,省略,完整的输出大约 1000 行,大家可以自行运行查看结果
1 0
610
time is:0.002106189727783203

此处我使用了 functools 包中提供的 lru_cache 缓存装饰器,用于缓存在计算斐波那契数列时重复的计算值。

从运行结果可以看到,不使用装饰器时,函数进行了大量的重复计算,导致最后的运行耗时和使用了装饰器的结果差了好几个数量级。

总结
带参数的装饰器为我们提供了极大的灵活性,使得我们可以根据不同的需求来调整函数的行为。在实际应用中,带参数的装饰器可以用于多种场景,如自定义日志、缓存、控制函数的执行行为等等。

标签:return,chof,Python,代码,优雅,def,com,装饰,decorator
From: https://www.cnblogs.com/bkbk123/p/18538557

相关文章

  • 告别复杂判断!Python 中实现函数重载的终极技巧
    引言说到函数重载,学过Java的同学应该不陌生,最常用的地方应该就是打印log了,对于不同的参数,调用的是不同的重载函数。那么Python如何实现函数重载呢?重载概念函数重载是指在同一作用域内,允许多个同名函数存在,但它们的参数列表不同。虽然许多编程语言(如Java和C++)支持函数......
  • 如何正确保护 Python 代码,不是 Pyinstaller
    引言在开发Python软件或者脚本时,为了保护Python代码不被盗用或篡改,我们需要借助一些工具来保护我们的源代码。通常情况下,我们可能会用Pyinstaller来保护我们的代码,并且将代码打包成可以在任何电脑上运行的单个文件。但是,Pyinstaller打包后的程序,只是将源代码编译成了pyc......
  • 怎么启动python脚本文件
    创建一个简单的python入门代码,以便示范。存储文件并复制该python文件的存储路径。使用cd命令切换工作目录到python文件所在的目录。输入变量环境中的python路径和python文件的名字。回车执行后,可完成命令行的python文件运行。......
  • 如何用python求导数
    打开python运行环境。导入微分的模块包:fromsympyimport*。定义符号变量:x=symbols('x')定义一个函数:f=x**9diff=diff(f,x)求导最后输入diff,即可显示其变量值了。......
  • Python decimal模块用法
    decimal模块:decimal意思为十进制,这个模块提供了十进制浮点运算支持1.可以传递给Decimal整型或者字符串参数,但不能是浮点数据,因为浮点数据本身就不准确。    在Python中,将变量声明为 Decimal 类型通常用于需要高精度和小数运算的场合。Decimal 类型属于 deci......
  • 状态总览界面相关代码
    运行情况概览日志索引数量{{log.indices}}日志总条数{{overviewData.documentsNum}}日志总量{{overviewData.data}}用户总数{{log.userNum}}昨日登录次数{{log.loginNum}}昨日查询次数{{log.searchNum}}<divclass="sidershadow">......
  • 【Python知识宝库】快速了解 `isinstance()` 的原理、作用和使用场景
    ......
  • Cocos Creator 如何调试代码?
    一、方式调试代码两种方式: 在VScode中调试 在浏览器中调试二、调试一:VSCode中Chrome浏览器打开VSCode中的插件下载DebuggerforChrome/JavaScriptDebugger打开CocosCreator点击菜单中的开发者选项选择VisualStudioCode工作流->添加Chromedebug配置,......
  • python+flask计算机毕业设计航空公司货运管理系统(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、选题背景关于航空公司货运管理系统的研究,现有研究多侧重于航空货运的某一单独环节,如货运流程优化或者资源配置等方面。专门针对航空公司货运管......
  • python-26-Python ORM系列之pymysql实现对数据库的增删改查及新建表
    python-26-PythonORM系列之pymysql实现对数据库的增删改查及新建表一.简介在Python基础系列ORM部分我们为大家介绍了如何搭建MySQL数据和MySQL一些访问配置,同时细节的同学应该已经了解到了ORM的2个库pymysql和sqlalchemy;PyMySQL—MySQL数据库驱动,用于与MySQL数据库......