python 进阶篇 函数装饰器和类装饰器
函数装饰器
简单装饰器
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__()接受一个函 ...
随机推荐
- HTML 基础(五)
一.列表 有序列表 无序列表 自定义列表 无序列表 无序列表是一个项目的列表,此列项目使用粗体圆点进行标记 无序列表使用 <ul> 标签 <ul> <li>Coff ...
- [讲解]网络流最大流dinic算法
网络流最大流算法dinic ps:本文章不适合萌新,我写这个主要是为了复习一些细节,概念介绍比较模糊,建议多刷题去理解 例题:codevs草地排水,方格取数 [抒情一下] 虽然老师说这个多半不考,但是 ...
- Python turtle库的应用——蛇
turtle库介绍 1.Turtle中的turtle.setup()函数用于启动一个图形窗口,它有四个参数 turtle.setup(width, height, startx, starty) 分别 ...
- 【3D】PoseCNN姿态检测网络复现过程记录
最近在研究室内6D姿态检测相关问题,计划在PoseCNN网络基础上进行改进实现.但是在第一步的复现过程中踩了无数的坑,最终成功运行了demo,但目前数据集train还是遇到了一些问题.有问题欢迎一起交 ...
- ssh-add和ssh-agent
注: 因为在ssh-agent异常关闭或者新开窗口是会导致ssh-add找不到私钥,导致添加的私钥无效,所以下面使用keychain管理 ssh-add 参数 -l 查看代理中的私钥 -L 查看代理中 ...
- cls
class : python中cls代表的是类的本身,相对应的self则是类的一个实例对象. class Person(object): def __init__(self, name, age): ...
- Elasticsearch 核心术语概念
Elasticsearch 相当于一个关系型数据库 索引 index 类型 type 文档 document 字段 fields 跟关系型数据库对比 Elasticsearch 相当于一个数据库 索引 ...
- python--爬虫(XPath与BeautifulSoup4)
获取页面内容除使用正则意外,还可以使用XPath,其原理是将html代码转换为xml格式,然后使用XPath查找html节点或元素. 选取节点 XPath使用路径表达式来选取XML文档中的节点或节点集 ...
- 微信小程序mpvue-动态改变navigationBarTitleText值
通过JS动态 改变navigationBarTitleText的值 能否通过JS动态改变navigationBarTitleText的值? 方法一:可以在onLoad方法中通过wx.setNaviga ...
- 家庭记账本app进度之关于单选按钮的相关操作(添加点击按钮事件以及点击单选更改事件)
这次主要是通过代码实现了android中的相关单选按钮的相关操作,之后再最下面有一个按钮,当点击这个按钮的时候,会获取当上面的相关信息,之后再下方会进行相应的文字显示,获取的信息不同显示的信息也不会一 ...