导航:首页 > 编程语言 > python类装饰器参数

python类装饰器参数

发布时间:2025-05-14 15:32:51

❶ “低门槛 手把手”python 装饰器(Decorators)原理说明

本文目的是由浅入深地介绍python装饰器原理

装饰器(Decorators)是 Python 的一个重要部分

其功能是, 在不修改原函数(类)定义代码的情况下,增加新的功能

为了理解和实现装饰器,我们先引入2个核心操作:

在这个例子中,函数hi的形参name,默认为'world'

在函数内部,又定义了另一个函数 howdoyoudo,定义这个函数时,将形参name作为新函数的形参name2的默认值。

因此,在函数内部调用howdoyoudo()时,将以调用hi时的实参为默认值,但也可以给howdoyoudo输入其他参数。

上面的例子运行后输出结果为:

这里新定义的howdoyoudo可以称作一个“闭包”。不少关于装饰器的blog都提到了这个概念,但其实没必要给它取一个多专业的名字。我们知道闭包是 函数内的函数 就可以了

当我们进行 def 的时候,我们在做什么?

这时,hi函数,打印一个字符串,同时返回一个字符串。

但hi函数本身也是一个对象,一个可以执行的对象。执行的方式是hi()。

这里hi和hi()有本质区别,

hi 代表了这个函数对象本身

hi() 则是运行了函数,得到函数的返回值。

作为对比,可以想象以下代码

此时也是b存在,可以正常使用。

我们定义2个函数,分别实现自加1, 自乘2,

再定义一个函数double_exec,内容是将某个函数调用2次

在调用double_exec时,可以将函数作为输入传进来

输出结果就是

7

27

同样,也可以将函数作为输出

输出结果为

6

10

有了以上两个核心操作,我们可以尝试构造装饰器了。

装饰器的目的: 在不修改原函数(类)定义代码的情况下,增加新的功能

试想一下,现在有一个原函数

在不修改原函数定义代码的情况下,如果想进行函数内容的添加,可以将这个函数作为一个整体,添加到这样的包裹中:

我们定义了一个my_decorator函数,这个函数进行了一种操作:

对传入的f,添加操作(运行前后增加打印),并把添加操作后的内容连同运行原函数的内容,一起传出

这个my_decorator,定义了一种增加前后打印内容的行为

调用my_decorator时,对这个行为进行了操作。

因此,new_function是一个在original_function上增加了前后打印行为的新函数

这个过程被可以被称作装饰。

这里已经可以发现,装饰器本身对于被装饰的函数是什么,是不需要考虑的。装饰器本身只定义了一种装饰行为,这个行为是通过装饰器内部的闭包函数()进行定义的。

运行装饰前后的函数,可以清晰看到装饰的效果

我们复现一下实际要用装饰器的情况,我们往往有一种装饰器,想应用于很多个函数,比如

此时,如果我们想给3个print函数都加上装饰器,需要这么做

实际调用的时候,就需要调用添加装饰器的函数名了

当然,也可以赋值给原函数名

这样至少不需要管理一系列装饰前后的函数。

同时,在不需要进行装饰的时候,需要把

全部删掉。

事实上,这样并不方便,尤其对于更复杂的装饰器来说

为此,python提供了一种简写方式

这个定义print1函数前的@my_decorator,相当于在定义完print1后,自动直接运行了

不论采用@my_decorator放在新函数前,还是显示地重写print1 = my_decorator(print1),都会存在一个问题:

装饰后的函数,名字改变了(其实不止名字,一系列的索引都改变了)

输出结果为:

这个现象的原因是,装饰行为本身,是通过构造了一个新的函数(例子中是wrap_func函数)来实现装饰这个行为的,然后把这个修改后的函数赋给了原函数名。

这样,会导致我们预期的被装饰函数的一些系统变量(比如__name__)发生了变化。

对此,python提供了解决方案:

经过这个行为后,被装饰函数的系统变量问题被解决了

输出结果为

刚才的例子都比较简单,被装饰的函数是没有参数的。如果被装饰的函数有参数,只需要在定义装饰行为时(事实上,这个才更通用),增加(*args, **kwargs)描述即可

之前的描述中可以感受到,对于例子中的装饰行为(前后加打印),函数被装饰后,本质上是调用了新的装饰函数wrap_func。

因此,如果原函数需要有输入参数传递,只需要在wrap_func(或其他任意名字的装饰函数)定义时,也增加参数输入(*args, **kwargs),并将这些参数,原封不动地传给待装饰函数f。

这种定义装饰行为的方式更具有普遍性,忘记之前的定义方式吧

我们试一下

输出

这里需要注意的是,如果按照以下的方式定义装饰器

那么以下语句将不会执行

因为装饰后实际的函数wrap_func(虽然名字被改成了原函数,系统参数也改成了原函数),运行到return f(*args, **kwargs) 的时候已经结束了

因为装饰器my_decorator本身也是可以输入的,因此,只需要在定义装饰器时,增加参数,并在后续函数中使用就可以了,比如

此时装饰器已经可以有输入参数了

输出

你可能发现,为什么不用简写版的方法了

因为以上代码会报错!!

究其原因,虽然

等价于

但是,

并不等价于

这本身和@语法有关,使用@my_decorator时,是系统在应用一个以单个函数作为参数的闭包函数。即,@是不能带参数的。

但是你应该发现了,之前的@wraps(f)不是带参数了吗?请仔细观察以下代码

通过一层嵌套,my_decorator_with_parma本质上是返回了一个参数仅为一个函数的函数(my_decorator),但因为my_decorator对my_decorator_with_parma来说是一个闭包,my_decorator_with_parma是可以带参数的。(这句话真绕)

通过以上的定义,我们再来看

可以这么理解,my_decorator_with_parma(msg='yusheng')的结果是原来的my_decorator函数,同时,因为my_decorator_with_parma可以传参,参数实际上是参与了my_decorator的(因为my_decorator对my_decorator_with_parma是闭包), my_decorator_with_parma(msg='yusheng') 全等于 一个有参数参加的my_decorator

因此,以上代码等价于有参数msg传递的

比较绕,需要理解一下,或者干脆强记这种范式:

以上范式包含函数的输入输出、装饰器的输入,可以应对大部分情况了。

实验一下:

输出

以上是一个log装饰器,利用datetime统计了函数的耗时,

并且,装饰器可以进行输出文件操作,如果给出了文件路径,则输出文件,否则就打印。

利用这个装饰器,可以灵活地进行耗时统计

不设置输出文件地址,则打印。运行结果为:

也可以输出到文件

输出结果为

同时在当前目录生成了一个test.log 文件,内容为:

以上的装饰器都是以函数形式出现的,但我们可以稍做改写,将装饰器以类的形式实现。

这个装饰器类Log 上个例子里的装饰器函数log功能是一样的,同时,这个装饰器类还可以作为基类被其他继承,进一步增加功能。

原文 http://www.cnblogs.com/yushengchn/p/15636944.html

❷ Python 中的 dataclass 装饰器详解

Python 3.7及以上版本引入了dataclass装饰器,这是一种简化类创建的方法。dataclass能自动生成特殊方法,如__init__、__repr__、__eq__等,从而减少重复代码。

使用dataclass装饰器非常简单,只需在类定义前加上@dataclass装饰器。例如,定义一个包含x和y属性的Point类,dataclass装饰器会自动生成所需的方法。

dataclass支持字段类型注解,方便阅读代码,并为IDE提供类型提示。例如,给字段指定类型,如age和address。

可以为字段设置默认值或使用默认工厂函数。例如,设置age字段的默认值为0,address字段的默认值为'Unknown'。

dataclass自动生成的__repr__方法按属性声明顺序输出对象的字符串表示。若需自定义,可手动实现该方法。

默认情况下,dataclass生成的类是可变的。若希望生成不可变类,可在类定义中添加frozen=True参数。

dataclass支持嵌套,可在类中使用其他dataclass构建复杂数据结构。

dataclass装饰器提供了一种简单而强大的类创建方式,提高类的可读性和可维护性。通过字段类型注解、默认值和默认工厂函数,以及支持嵌套,dataclass提供了更多灵活选项。添加frozen=True参数可轻松创建不可变对象,提高数据安全性。

dataclass是一个强大的工具,简化了类创建和管理。在数据处理和对象建模方面,使用dataclass装饰器可让代码更清晰,减少样板代码。深入理解dataclass特性,能更好地运用这一功能,提高代码质量和开发效率。

❸ python 带可变参数的装饰器怎么用

装饰器本身是用来是为一个函数是实现新的功能,并且不改变原函数的代码以及调用方式。

遇到这样一种问题:

众多函数调用了你写的装饰器,但客户有需求说,我想实现我可以随之控制装饰器是否生效。

那你就不可能在得到命令的时候去原函数头部去做删除和添加装饰器调用的命令。这是就可以用到带参数的装饰器,定义一个开关,调用装饰器的时候,把这个装饰器的开关参数给传递进去,这样当开关打开的时候装饰器生效,关闭的时候则只执行原函数的代码。

举例:开关参数为True的时候执行过程:

F=True#step1装饰器的开关变量
defouter(flag):#step2
defwrapper(func):#step4
definner(*args,**kwargs):#stpe6
ifflag:#step9
print('before')#step10
ret=func(*args,**kwargs)#step11执行原函数
print('after')#step13
else:
ret=func(*args,**kwargs)
print('123')
returnret#step14
returninner#step7
returnwrapper#step5

@outer(F)#先执行step3:outer(True)这个函数,然后step6:@wrapper#此处把开关参数传递给装饰器函数
defhahaha():
pass#step12
hahaha()#step8相当于inner()

开关参数为False的时候执行过程:

F=False#stpe1装饰器的开关变量
defouter(flag):#step2
defwrapper(func):#step4
definner(*args,**kwargs):#stpe6
ifflag:#step9
print('before')
ret=func(*args,**kwargs)
print('after')
else:
ret=func(*args,**kwargs)#step10执行原函数
print('123')#step12
returnret#step13
returninner#step7
returnwrapper#step5

❹ Python笔记:Python装饰器

装饰器是通过装饰器函数修改原函数的一些功能而不需要修改原函数,在很多场景可以用到它,比如① 执行某个测试用例之前,判断是否需要登录或者执行某些特定操作;② 统计某个函数的执行时间;③ 判断输入合法性等。合理使用装饰器可以极大地提高程序的可读性以及运行效率。本文将介绍Python装饰器的使用方法。

python装饰器可以定义如下:

输出:

python解释器将test_decorator函数作为参数传递给my_decorator函数,并指向了内部函数 wrapper(),内部函数 wrapper() 又会调用原函数 test_decorator(),所以decorator()的执行会先打印'this is wrapper',然后打印'hello world', test_decorator()执行完成后,打印 'bye' ,*args和**kwargs,表示接受任意数量和类型的参数。

装饰器 my_decorator() 把真正需要执行的函数 test_decorator() 包裹在其中,并且改变了它的行为,但是原函数 test_decorator() 不变。

一般使用如下形式使用装饰器:

@my_decorator就相当于 decorator = my_decorator(test_decorator) 语句。

内置装饰器@functools.wrap可用于保留原函数的元信息(将原函数的元信息,拷贝到对应的装饰器函数里)。先来看看没有使用functools的情况:

输出:

从上面的输出可以看出test_decorator() 函数被装饰以后元信息被wrapper() 函数取代了,可以使用@functools.wrap装饰器保留原函数的元信息:

输出:

装饰器可以接受自定义参数。比如定义一个参数来设置装饰器内部函数的执行次数:

输出:

Python 支持多个装饰器嵌套:

装饰的过程:

顺序从里到外:

test_decorator('hello world') 执行顺序和装饰的过程相反。

输出:

类也可以作为装饰器,类装饰器主要依赖__call__()方法,是python中所有能被调用的对象具有的内置方法(python魔术方法),每当调用一个类的实例时,__call__()就会被执行一次。

下面的类装饰器实现统计函数执行次数:

输出:

下面介绍两种装饰器使用场景

统计函数执行所花费的时间

输出:

在使用某些web服务时,需要先判断用户是否登录,如果没有登录就跳转到登录页面或者提示用户登录:

--THE END--

❺ python装饰器使用

装饰器是从英文decorator翻译过来的,从字面上来看就是对某个东西进行修饰,增强被修饰物的功能,下面我们对装饰器做下简单介绍。

一、怎么编写装饰器

装饰器的实现很简单,本质是一个可调用对象,可以是函数、方法、对象等,它既可以装饰函数也可以装饰类和方法,为了简单说明问题,我们实现一个函数装饰器,如下代码:

有了这个装饰器,我们就可以打印出什么时候开始和结束调用函数,对于排查函数的调用链非常方便。

二、带参数的装饰器

上面的例子无论什么时候调用sum都会输出信息,如果我们需要按需输出信息怎么实现呢,这时就要用到带参数的装饰器了,如下代码:

对sum使用装饰器时没有参数,这时debug为0,所以调用sum时不会输出函数调用相关信息。

对multi使用装饰器时有参数,这时debug为1,所以调用multi时会输出函数调用相关信息。

三、函数名字问题

当我们打印被装饰后的函数名字时,不知道大家有没发现输出的不是函数本身的名字,如下代码会输出‘wrap’而不是‘sum’:

有时这种表现并不是我们想要的,我们希望被装饰后的函数名字还是函数本身,那要怎么实现呢?很简单,只需要引入functools.wraps即可,如下代码就会输出‘sum’了:

看完后是不是觉得python装饰器很简单,只要了解它的本质,怎么写都行,有好多种玩法呢。

❻ 装饰器(Decorator)

装饰器是Python中一种允许在代码运行期间动态增加功能的工具。以下是关于装饰器的详细解答:

  1. 定义与本质

    • 装饰器本质上是Python中的函数或类。
    • 它允许在不修改原始代码的情况下,为函数或方法添加新功能。
  2. 关键特点

    • 参数为函数:装饰器接收一个函数作为参数。
    • 返回值为函数:装饰器返回一个新的函数,该新函数在调用时会执行原始函数并附加额外的功能。
  3. 组成原则

    • 装饰器涉及函数、高阶函数、返回值、嵌套函数和语法糖等概念。
    • 高阶函数是指可以接收函数作为参数或返回函数作为结果的函数。
  4. 功能扩展

    • 通过装饰器,可以在函数执行前后添加各种新功能,如日志记录、性能测试、事务处理、缓存、权限校验等。
    • 装饰器不修改原函数代码,不改变调用方式,仅增强功能。
  5. 实现示例

    • 一个常见的实现示例是通过装饰器添加统计函数运行时间的功能。
    • 装饰器内部会使用嵌套函数来包装原始函数,并在调用前后添加额外的逻辑。
  6. 参数传递与返回值处理

    • 对于有参函数的装饰,装饰器需要处理额外的参数。
    • 装饰器可以返回与原始函数相同的返回值,也可以返回修改后的结果。
  7. 多个装饰器的执行顺序

    • 当多个装饰器应用于同一个函数时,它们会按照从外到内的顺序嵌套。
    • 函数的执行顺序则遵循从内到外的顺序,即最内层的装饰器最先执行,最外层的装饰器最后执行。
  8. 应用场景与优势

    • 装饰器在代码复用、功能扩展、日志记录、性能测试等方面具有广泛应用。
    • 它能够提升代码的可维护性和可扩展性,使代码更加简洁和易于管理。

通过理解装饰器的工作原理和实现方式,开发者可以更加高效地编写和维护Python代码。

阅读全文

与python类装饰器参数相关的资料

热点内容
pid命令 浏览:886
一天一图学会python可视化 浏览:307
魔兽编辑文本命令串 浏览:495
android中view绘制 浏览:796
安卓机内存删除怎么恢复 浏览:329
Qt环境的编译软件放到linux 浏览:212
联创打印系统怎么连接服务器 浏览:935
杭州行政命令 浏览:160
如何查找服务器日志 浏览:801
加密的钥匙扣怎么写 浏览:579
文件夹更新不了怎么办 浏览:475
压缩机指示灯亮是什么原因 浏览:956
什么app订酒店半价 浏览:765
中老年解压神器 浏览:243
讯飞语音ttsandroid 浏览:468
腰椎压缩性骨折术后能坐车吗 浏览:507
python类装饰器参数 浏览:349
均线pdf微盘 浏览:792
女生喜欢玩的解压游戏 浏览:442
支付宝暗号加密操作 浏览:134