函数装饰器
-
简单装饰器
def my_decorator(func):
def wrapper():
print('wrapper of decorator')
func()
return wrapper def greet():
print('hello world') greet = my_decorator(greet)
greet() # 输出
# wrapper of decorator
# hello world上述代码在 Python 中有更简单、更优雅的表示:
def my_decorator(func):
def wrapper():
print('wrapper of decorator')
func()
return wrapper @my_decorator
def greet():
print('hello world') greet() # 输出
# wrapper of decorator
# hello world -
带参数的装饰器
def my_decorator(func):
def wrapper(*args, **kwargs):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper @my_decorator
def greet(message):
print(message) greet('hello world') # 输出
# wrapper of decorator
# hello world -
自定义参数的装饰器
def repeat(num):
def my_decorator(func):
def wrapper(*args, **kwargs):
for i in range(num):
print('wrapper of decorator {}'.format(i))
func(*args, **kwargs)
return wrapper
return my_decorator @repeat(4)
def greet(message):
print(message) greet('hello world') # 输出:
# wrapper of decorator 0
# hello world
# wrapper of decorator 1
# hello world
# wrapper of decorator 2
# hello world
# wrapper of decorator 3
# hello world -
原函数还是原函数吗?
试着打印出 greet() 函数的一些元信息:
greet.__name__
## 输出
'wrapper' help(greet)
# 输出
Help on function wrapper in module __main__: wrapper(*args, **kwargs)greet()
函数被装饰以后,它的元信息变了。元信息告诉我们“它不再是以前的那个greet()
函数,而是被wrapper()
函数取代了”。为了解决这个问题,通常使用内置的装饰器
@functools.wrap
,它会帮助保留原函数的元信息(也就是将原函数的元信息,拷贝到对应的装饰器函数里)。import functools def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper @my_decorator
def greet(message):
print(message) greet.__name__ # 输出
'greet'
类装饰器
实际上,类也可以作为装饰器。类装饰器主要依赖于函数__call__()
,每当你调用一个类的示例时,函数__call__()
就会被执行一次。
class Count:
def __init__(self, func):
self.func = func
self.num_calls = 0
def __call__(self, *args, **kwargs):
self.num_calls += 1
print('num of calls is: {}'.format(self.num_calls))
return self.func(*args, **kwargs)
@Count
def example():
print("hello world")
example()
# 输出
num of calls is: 1
hello world
example()
# 输出
num of calls is: 2
hello world
我们定义了类 Count,初始化时传入原函数 func()
,而__call__()
函数表示让变量 num_calls 自增 1,然后打印,并且调用原函数。因此,在我们第一次调用函数 example()
时,num_calls 的值是 1,而在第二次调用时,它的值变成了 2
装饰器的应用
身份认证 authenticate
日志记录
输入合理性检查 validation_check
-
缓存 lru_cache
通常使用缓存装饰器,来包裹这些检查函数,避免其被反复调用,进而提高程序运行效率,比如写成下面这样
@lru_cache
def check(param1, param2, ...) # 检查用户设备类型,版本号等等
...
python 进阶篇 函数装饰器和类装饰器的更多相关文章
-
python进阶篇
python进阶篇 import 导入模块 sys.path:获取指定模块搜索路径的字符串集合,可以将写好的模块放在得到的某个路径下,就可以在程序中import时正确找到. import sys ...
-
Python进阶(十四)----空间角度研究类,类与类之间的关系
Python进阶(十四)----空间角度研究类,类与类之间的关系 一丶从空间角度研究类 对象操作对象属性 class A(): address = '沙河' def __init__(self, na ...
-
Python进阶(二)----函数参数,作用域
Python进阶(二)----函数参数,作用域 一丶形参角度:*args,动态位置传参,**kwargs,动态关键字传参 *args: 动态位置参数. 在函数定义时, * 将实参角度的位置参数聚合 ...
-
typescript装饰器定义 类装饰器 属性装饰器 装饰器工厂
/* 装饰器:装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为. 通俗的讲装饰器就是一个方法,可以注入到类.方法.属性参数上来扩展类.属性.方法.参数的功能. 常 ...
-
Python进阶(三)----函数名,作用域,名称空间,f-string,可迭代对象,迭代器
Python进阶(三)----函数名,作用域,名称空间,f-string,可迭代对象,迭代器 一丶关键字:global,nonlocal global 声明全局变量: 1. 可以在局部作用域声明一 ...
-
Python进阶(一)----函数
Python进阶(一)----函数初识 一丶函数的初识 什么函数: 函数是以功能为导向.一个函数封装一个功能 函数的优点: 1.减少代码的重复性, 2.增强了代码的可读性 二丶函数的结构 ...
-
Python入门篇-函数、参数及参数解构
Python入门篇-函数.参数及参数解构 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.函数概述 1>.函数的作用即分类 函数 数学定义:y=f(x) ,y是x的函数,x ...
-
Java类载入器(一)——类载入器层次与模型
类载入器 虚拟机设计团队把类载入阶段中的"通过一个类的全限定名来获取描写叙述此类的二进制字节流"这个动作放到Java虚拟机外部去实现.以便让应用程序自己决定怎样去获取所须要的类 ...
-
python 装饰器(五):装饰器实例(二)类装饰器(类装饰器装饰函数)
回到装饰器上的概念上来,装饰器要求接受一个callable对象,并返回一个callable对象(不太严谨,详见后文). 那么用类来实现也是也可以的.我们可以让类的构造函数__init__()接受一个函 ...
随机推荐
-
mac安装IE浏览器
1.首先得下载一个WineBottler for mac. 2.下载完毕之后,打开dmg文件后将WineBottler Combo里面的Wine和WineBottler这两个程序拖拉进应用程序. 3. ...
-
centos 如何用 rsyslog 搭建本地日志服务(续1: omprog模块与php deamon的配合使用)
上一篇说到了如何用 rsyslog 搭建本地的日志服务,地址在这里,没有看的童鞋可以先瞅一眼 : http://www.cnblogs.com/smallrookie/p/5677004.html 显 ...
-
word 中Sentences、Paragraph等含义和用法
word 中有Words,Characters,Sentences.Paragraph,Sections 具体含义如下表达式 含义 返回的对象 Words(index) ...
-
css hack 兼容性
做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我们会极不情愿的使用这个不太友好的方式来 达到大家要求的页面表现.我个人是不太推荐使用hack的,要知 ...
-
MYSQL select ....outfile.....from.....
select .... outfile 'file_path' fields terminate by '\t' lines terminate by '\r\n' from table_name; ...
-
Windows服务框架与服务的编写
从NT内核开始,服务程序已经变为一种非常重要的系统进程,一般的驻守进程和普通的程序必须在桌面登录的情况下才能运行,而许多系统的基础程序必须在用户登录桌面之前就要运行起来,而利用服务,可以很方便的实现这 ...
-
新概念英语(1-29)Come in, Amy.
How must Amy clean the floor? A:Come in, Amy. Shut the door, please. This bedroom's very untidy. B:W ...
-
小米平板6.0系统如何无ROOT激活xposed框架的步骤
在较多企业的引流,或业务操作中,基本上都需要使用安卓的黑高科技术Xposed框架,近期,我们企业购买了一批新的小米平板6.0系统,基本上都都是基于7.0以上系统,基本上都不能够获得ROOT的su权限, ...
-
百战程序员——Spring框架
什么是容器,我们学过了哪些容器,Spring与我们之前学习的容器有哪些异同点? 容器可以管理对象的生命周期.对象与对象之间的依赖关系,您可以使用一个配置文件(通常是XML),在上面定义好对象的名称.如 ...
-
learn python the hard way习题31~40总结以及列表的扩展知识
Python 中的列表: 形式:[ 表示打开一个列表,中间的项目用 , 隔开,然后列表以 ] 结束. for循环 两种形式: for i in ArrayName: for i in range(0, ...