Python 标准库中的装饰器
题目描述
1、简单举例 Python 标准库中的装饰器
2、说说你用过的 Python 标准库中的装饰器
1. 首先,我们比较熟悉,也是比较常用的 Python 标准库提供的装饰器有:property,classmethod,staticmethod,functools.wraps四个。这四个的可考点比较多,这里将分别说明:
首先先来说明 functools.wraps,这个我们在之前翻译装饰器时已经谈到过。这里我们同样用代码来说明吧。
# 比如一个简单的用来统计代码运行时长的装饰器
import time
def method_spend(func):
def inner(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print('[%0.8fs] %s --> %s' % ((end-start), func.__name__, result))
return result
return inner
@method_spend
def test():
print(<span data-raw-text="" "="" data-textnode-index="41" data-index="580" class="character" style=";padding: 0px">"Hello World<span data-raw-text="" "="" data-textnode-index="41" data-index="592" class="character" style=";padding: 0px">")
test()
# outputs:
# Hello World
# [0.00001907s] test --> None
test = test
print(test.__name__) # inner
从代码可以看出,经过装饰之后,被装饰函数的 name__ 属性被修改了,变成了装饰后的函数。(实际上 __doc 属性也一样被修改了)。而functools.wraps 的作用就是保存被装饰函数的属性。
引用《流畅的Python》中的话
functools.wraps 的作用是协助构建行为良好的装饰器。
使用示例:
import time
import functools
def method_spend(func):
@functools.wraps(func) # 使用 functools.wraps
def inner(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print('[%0.8fs] %s --> %s' % ((end-start), func.__name__, result))
return result
return inner
@method_spend
def test():
print(<span data-raw-text="" "="" data-textnode-index="92" data-index="1213" class="character" style=";padding: 0px">"Hello World<span data-raw-text="" "="" data-textnode-index="92" data-index="1225" class="character" style=";padding: 0px">")
test()
# outputs:
# Hello World
# [0.00001907s] test --> None
test = test
print(test.__name__) # test
接着我们来谈谈 staticmethod 和 classmethod。这个相对考得比较少,但也需要知道。classmethod 可类比于 JAVA 中的类方法,它第一个参数必须是类对象,而不是类的实例对象。而 staticmethod 作用与 classmethod 类似,可不能过实例对象来调用,但它不强制参数,可以是任何参数。厦门叉车公司电话是多少
最后,来简单说下 property 。property 比较重要,后面会再开专题介绍。这里只简单说明它的作用,那就是实现类似 JAVA 中的私有变量的封装,并提供一个获取方法,类似于getXxx 和 setXXX 方法。用代码说话:
# 实现一个简单的 人 类,然后对年龄进行私有化
class Person(object):
@property
def age(self):
return self._age
# 这样的好处是,可以自定义赋值的逻辑,比如对数据进行某种验证
@age.setter # 这里 age 与 @property 包装的函数名一致
def age(self, value):
if value > 18: # 永远18
value = 18
self._age = value
p = Person()
p.age = 18 # 实际上调用的是 p.set_age(60)
print(p.age) # 实际上调用的是 p.get_age()
2. functools.lru_cache 装饰器。从字面来理解,lru 为 <span data-raw-text="" "="" data-textnode-index="145" data-index="2010" class="character" style=";padding: 0px">"Least Recently Used<span data-raw-text="" "="" data-textnode-index="145" data-index="2030" class="character" style=";padding: 0px">"即最近最少使用,cache,不用说,缓存的意思。所以我们就大致知道这个装饰器的作用了,就是缓存部分数据,如果缓存的数据超过限制,就通过 最近最少使用 的规则来淘汰数据。来看一个简单的例子:
# 一个简单的缓存用户的示例
import functools
@functools.lru_cache()
def get_user_info(user_id):
# 根据用户 id 从数据库获取用户信息,这里简单的输出 id
print(<span data-raw-text="" "="" data-textnode-index="158" data-index="2250" class="character" style=";padding: 0px">"finding by %s<span data-raw-text="" "="" data-textnode-index="158" data-index="2264" class="character" style=";padding: 0px">" % user_id)
return user_id
print(get_user_info(1)) # outputs: finding by 1 1
print(get_user_info(1)) # outputs: 1 (可以发现直接拿到了结果)
print(get_user_info(1.0)) # outputs: 1 (可以发现这里没有区分浮点数与整数)
print(get_user_info(2)) # outputs: funding by 2 2
这里需要注意的是, lru_cache 有两个可选的参数配置:
functools.lru_cache(maxsize=128, typed=False)
其中,maxsize 指定可以缓存多少个结果,缓存满了之后,旧的结果被丢弃。一般建议 maxsize 的值是 2 的幂。typed 参数如果设置为 True,会区分不同类型的结果。比如会将 1 和 1.0 区分开。
3. functools.singledispatch 装饰器。这个也比较好理解,它的作用是用来将if…elif..elif…else 这样的代码进行模块化。有点类似于 JAVA 中重载的意味,但又不全是。它是在 Python 3.4 中新增的。我们来看一个简单的例子:
# 一个简单的根据不同类型的数据来进行不同的展示
import functools
@functools.singledispatch
def my_print(obj):
print(<span data-raw-text="" "="" data-textnode-index="197" data-index="2915" class="character" style=";padding: 0px">"%s -> %s<span data-raw-text="" "="" data-textnode-index="197" data-index="2924" class="character" style=";padding: 0px">" % (obj, type(obj)))
@my_print.register(str) # 如果是字符串类型,相当于 if isinstance(str_msg, str)
def _(str_msg):
print(<span data-raw-text="" "="" data-textnode-index="206" data-index="3037" class="character" style=";padding: 0px">"我是str<span data-raw-text="" "="" data-textnode-index="206" data-index="3043" class="character" style=";padding: 0px">")
print(<span data-raw-text="" "="" data-textnode-index="209" data-index="3055" class="character" style=";padding: 0px">"%s -> %s<span data-raw-text="" "="" data-textnode-index="209" data-index="3064" class="character" style=";padding: 0px">" % (str_msg, type(str_msg)))
@my_print.register(int) # 如果是字符串类型,相当于 if isinstance(int_msg, int)
def _(int_msg):
print(<span data-raw-text="" "="" data-textnode-index="218" data-index="3185" class="character" style=";padding: 0px">"我是int<span data-raw-text="" "="" data-textnode-index="218" data-index="3191" class="character" style=";padding: 0px">")
print(<span data-raw-text="" "="" data-textnode-index="221" data-index="3203" class="character" style=";padding: 0px">"%s -> %s<span data-raw-text="" "="" data-textnode-index="221" data-index="3212" class="character" style=";padding: 0px">" % (int_msg, type(int_msg)))
my_print(<span data-raw-text="" "="" data-textnode-index="224" data-index="3250" class="character" style=";padding: 0px">"haha<span data-raw-text="" "="" data-textnode-index="224" data-index="3255" class="character" style=";padding: 0px">") # outputs: 我是str haha -> <class 'str'>
my_print(1) # outputs: 我是int 1 -> <class 'int'>
my_print([1]) # outputs: [1] -> <class 'list'>
Python 标准库中的装饰器的更多相关文章
- 标准库中的装饰器 lru_cache和全新的 singledispatch
Python 内置了三个用于装饰方法的函数:property.classmethod 和 staticmethod. 另一个常见的装饰器是 functools.wraps,它的作用是协助构建行为 良好 ...
- (转)python标准库中socket模块详解
python标准库中socket模块详解 socket模块简介 原文:http://www.lybbn.cn/data/datas.php?yw=71 网络上的两个程序通过一个双向的通信连接实现数据的 ...
- [python]在场景中理解装饰器
原来我也自己通过查资料,来学习python的装饰器,但是效果不好.因为没有接触过需要用到装饰器的场景,所以 一起的资料都只停留在纸面上,但是今天偶然看到了vimer的这篇文章:http://www.v ...
- C++实现python标准库中的Counter
看python standard library by exmple里面提到一个Counter容器,它像muliset一样,能够维持一个集合,并在常量时间插入元素.查询某个元素的个数,而且还提供了一个 ...
- Python标准库中的生成器函数
一.用于过滤的生成器函数 - 从输入的可迭代对象中产出元素的子集,而不修改元素本身 import itertools l1 = [1,2,3,4,5] l2 = [True,False,True,Fa ...
- 06.队列、python标准库中的双端队列、迷宫问题
class QueueUnderflow(ValueError): """队列为空""" pass class SQueue: def __ ...
- python标准库中socket模块详解
包含原理就是tcp的三次握手 http://www.lybbn.cn/data/datas.php?yw=71 这篇讲到了socket和django的联系 https://www.cnblogs.co ...
- 流畅的python第七章函数装饰器和闭包学习记录
本章讨论的话题 python如何计算装饰器句法 python如何判断变量是不是局部的(通过函数内部是否给变量赋值过来判断是否是局部变量) 闭包存在的原因和工作原理(闭包是一种函数,它会保留定义函数时存 ...
- [python标准库]XML模块
1.什么是XML XML是可扩展标记语言(Extensible Markup Language)的缩写,其中的 标记(markup)是关键部分.您可以创建内容,然后使用限定标记标记它,从而使每个单词. ...
随机推荐
- nuxt 脚手架创建nuxt项目中不支持es6语法的解决方案
node本身并不支持es6语法,我们通常在vue项目中使用es6语法,是因为,我们使用babel做过处理, 为了让项目支持es6语法,我们必须同时使用babel 去启动我们的程序,所以再启动程序中加 ...
- 关于vmware workstation10常见问题
简单的说明:win7和win10的解决办法都是这个,都可以用这个解决. 这是一个共性的问题. 出现这个问题的原因是: a.要么是系统更新没有及时正确的关闭虚拟机导致的; b.没有及时将虚拟机手动关闭再 ...
- python自动化之model进阶操作一
联合索引 遵循最左前缀索引 verbose_name 会在表名后面加s verbose_name_plural 就是表的原始名称 元信息 class UserInfo(models.Model): n ...
- SD卡受损,千万不要再格式化了
1.手机提示SD卡受损; 2.把内卡插入电脑后,提示格式化,点取消.然后查看一下属性; 3.点电脑上的“开始菜单”--“运行”- chkdsk H:/F (H:就是你的SD卡盘符,/F是修复参数); ...
- Android :Activity、Adapter、List的初步学习
Activity Activity 是一个应用组件,用户可与其提供的屏幕进行交互,以执行对手机应用操作. 每个 Activity 都会获得一个用于绘制其用户界面的窗口.窗口一般是会充满屏幕,但也不一定 ...
- iOS 折线图、柱状图的简单实现
首先我得感谢某位博主,非常抱歉,因为之前直接下载博主提供这篇文章的demo,然后去研究了,没记住博主的名字.再次非常感谢. 而这个dome我又修改了一些,完善了一些不美观的bug,当然还有,后面会陆续 ...
- Robosup3D平台搭建
目录 1.安装simspark及默认播放器 安装依赖库/下载simspark源码 编译并安装simspark 编译并安装rcssmonitor3d播放器 2.安装Roboviz播放器 安装java 安 ...
- pandas:对字符串类型做差分比较
1. 问题需求 某种行为最常发生时段.最少发生时段与X天前是否一致 需求变形:判断上下行数据是否一致 2. 预备知识 2.1 Series.ne(Series) 判断两个Series是否相等 impo ...
- Currency Exchange POJ - 1860 (spfa)
题目链接:Currency Exchange 题意: 钱的种类为N,M条命令,拥有种类为S这类钱的数目为V,命令为将a换成b,剩下的四个数为a对b的汇率和a换成b的税,b对a的汇率和b换成a的税,公式 ...
- SSISDB1:使用SSISDB管理Package
SSISDB 系列随笔汇总: SSISDB1:使用SSISDB管理Package SSISDB2:SSIS工程的操作实例 SSISDB3:Package的执行实例 SSISDB4:当前正在运行的Pac ...