博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python 标准库中的装饰器
阅读量:7011 次
发布时间:2019-06-27

本文共 3660 字,大约阅读时间需要 12 分钟。

题目描述

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("Hello World") 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("Hello World") 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("finding by %s" % 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("%s -> %s" % (obj, type(obj))) @my_print.register(str)  # 如果是字符串类型,相当于 if isinstance(str_msg, str) def _(str_msg):     print("我是str")     print("%s -> %s" % (str_msg, type(str_msg))) @my_print.register(int)  # 如果是字符串类型,相当于 if isinstance(int_msg, int) def _(int_msg):     print("我是int")     print("%s -> %s" % (int_msg, type(int_msg))) my_print("haha")  # outputs: 我是str haha -> 
my_print(1)  # outputs: 我是int 1 -> 
my_print([1]) # outputs: [1] -> 

转载于:https://www.cnblogs.com/xyou/p/9558180.html

你可能感兴趣的文章
c# process 输入输出
查看>>
Hibernate 一对一映射(共享主键)
查看>>
poj 2987(最大权闭合图+割边最少)
查看>>
在Mac下结合Xcode搭建Cocos2d-X开发环境!
查看>>
C#技术分享【PDF转换成图片——13种方案】(2013-07-25重新整理) .
查看>>
微信商业化解读
查看>>
jQuery学习笔记(DOM操作)
查看>>
intest
查看>>
C语言 数组 行优先 实现
查看>>
ORACLE 监听日志文件太大停止写监听日志引起数据库连接不上问题
查看>>
springMVC零配置吐槽
查看>>
程序员必须知道的10大基础实用算法及其讲解
查看>>
petshop4.0 具体解释之中的一个(系统架构设计)
查看>>
centos 安装http协议的git server
查看>>
设置 zend studio 默认编码为UTF8
查看>>
并行编程之多线程共享非volatile变量,会不会可能导致线程while死循环
查看>>
asp.net MVC3 + JQuery 的ajax简单使用
查看>>
第 1 章 策略模式【Strategy Pattern】
查看>>
eclipse 在Servers窗口创建一个Tomcat 6.0 Server失败
查看>>
DJANTO之FORM
查看>>