Python自学成才之路 带有参数的装饰器
时间:2022-07-23
本文章向大家介绍Python自学成才之路 带有参数的装饰器,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
文章目录
上一节留了点悬念。(上一节) 函数和装饰器都可以添加参数,但是装饰器结构上的区别在于装饰器是否带参数。
第一种:装饰器不带参数
看下面一个案例:
class my_decorate(object):
def __init__(self, f):
"""
如果装饰器不带参数,函数需要作为参数传递给这个类的构造器
"""
print("进入到 __init__")
self.f = f
def __call__(self, *args):
print("进入 __call__")
self.f(*args)
print("结束 __call__")
@my_decorate
def myFunction(arg1, arg2):
print('myFunction arguments:', arg1, arg2)
print("开始调用myfunction")
myFunction("say", "hello")
myFunction("hello", "again")
输出:
进入到 __init__
开始调用myfunction
进入 __call__
myFunction arguments: say hello
结束 __call__
进入 __call__
myFunction arguments: hello again
结束 __call__
注意,这里__init__只被调用了一次,进一步印证了上一节的说法,用类作为装饰器会先得到类实例,然后再去执行类实例。这里执行过程等价于:
myDecorate = my_decorate(myFunction)
myDecorate('say', 'hello')
myDecorate('hello', 'again')
试试打印出myFunction的类型print(type(myFunction)),返回的其实是my_decorate类型,被装饰器修饰的函数最终类型实际上是装饰器本身。
第二种:装饰器带参数
装饰器带参数后结构发生了较大的变化,这时__init__方法中的参数是装饰器的参数而不是函数,使用函数作为参数是在__call__方法中,而且__call__方法需要返回可调用对象。
class my_decorate(object):
def __init__(self, arg1, arg2, arg3):
print("进入 __init__()")
self.arg1 = arg1
self.arg2 = arg2
self.arg3 = arg3
def __call__(self, f):
print("进入 __call__()")
def wrapped_f(*args):
print("进入 wrapped_f()")
print("装饰器参数:", self.arg1, self.arg2, self.arg3)
f(*args)
print('执行完函数myfunction')
return wrapped_f
@my_decorate("hello", "world", 1)
def myFunction(*args):
if len(args) > 0:
print('this is myFunction args: %s' % str(args))
else:
print('this is myFunctions')
myFunction('hello', 'myfunction')
myFunction()
输出:
进入 __init__()
进入 __call__()
进入 wrapped_f()
装饰器参数: hello world 1
this is myFunction args: ('hello', 'myfunction')
执行完函数myfunction
进入 wrapped_f()
装饰器参数: hello world 1
this is myFunctions
执行完函数myfunction
因为装饰器有了参数,所以这个时候不能在__init__中接收函数作为参数。类比于装饰器无参的时候,当传递函数作为参数时返回的应该是一个可调用对象(在装饰器无参案例中,函数是传递到__init__方法中,等到的是myDecorate实例,myDecorate实例有实现__call__方法,所以是可调用的),而这个时候,函数参数是传递给了__call__方法,所以在__call__方法中返回了wrapped_f这个函数,函数肯定是可调用的。这个过程等价于:
myDecorate = my_decorate("hello", "world", 1)
wrapped_f = myDecorate(f)
wrapped_f('hello', 'myfunction')
wrapped_f()
- 如何写好一篇漏洞报告(国外篇)
- hbase源码系列(八)从Snapshot恢复表
- hbase源码系列(七)Snapshot的过程
- CVE-2017-3085:Adobe Flash泄漏Windows用户凭证
- hbase源码系列(九)StoreFile存储格式
- 如何确定恶意软件是否在自己的电脑中执行过?
- Carbondata源码系列(二)文件格式详解
- 挖洞经验 | 记一次针对Twitter(Periscope)API 的有趣挖洞经历
- 设计模式学习(二): 观察者模式 (C#)
- Carbondata源码系列(一)文件生成过程
- BoopSuite:基于Python编写的无线安全审计套件
- 设计模式学习(一):多用组合少用继承(C#)
- 在asp.net web api 2 (ioc autofac) 使用 Serilog 记录日志
- hbase源码系列(十三)缓存机制MemStore与Block Cache
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法