Python深入05 装饰器

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

 

装饰器(decorator)是一种高级Python语法。装饰器可以对一个函数、方法或者类进行加工。在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果。相对于其它方式,装饰器语法简单,代码可读性高。因此,装饰器在Python项目中有广泛的应用。

装饰器最早在Python 2.5中出现,它最初被用于加工函数和方法这样的可调用对象(callable object,这样的对象定义有__call__方法)。在Python 2.6以及之后的Python版本中,装饰器被进一步用于加工类。

 

装饰函数和方法

我们先定义两个简单的数学函数,一个用来计算平方和,一个用来计算平方差:

# get square sum
def square_sum(a, b):return a**2 + b**2# get square diff
def square_diff(a, b):return a**2 - b**2

print(square_sum(3, 4))
print(square_diff(3, 4))

在拥有了基本的数学功能之后,我们可能想为函数增加其它的功能,比如打印输入。我们可以改写函数来实现这一点:

# modify: print input# get square sum
def square_sum(a, b):print("intput:", a, b)return a**2 + b**2# get square diff
def square_diff(a, b):print("input", a, b)return a**2 - b**2

print(square_sum(3, 4))
print(square_diff(3, 4))

我们修改了函数的定义,为函数增加了功能。

 

现在,我们使用装饰器来实现上述修改:

def decorator(F):def new_F(a, b):print("input", a, b)return F(a, b)return new_F# get square sum
@decorator
def square_sum(a, b):return a**2 + b**2# get square diff
@decorator
def square_diff(a, b):return a**2 - b**2print(square_sum(3, 4))
print(square_diff(3, 4))

装饰器可以用def的形式定义,如上面代码中的decorator。装饰器接收一个可调用对象作为输入参数,并返回一个新的可调用对象。装饰器新建了一个可调用对象,也就是上面的new_F。new_F中,我们增加了打印的功能,并通过调用F(a, b)来实现原有函数的功能。

定义好装饰器后,我们就可以通过@语法使用了。在函数square_sum和square_diff定义之前调用@decorator,我们实际上将square_sum或square_diff传递给decorator,并将decorator返回的新的可调用对象赋给原来的函数名(square_sum或square_diff)。 所以,当我们调用square_sum(3, 4)的时候,就相当于:

square_sum = decorator(square_sum)
square_sum(3, 4)

我们知道,Python中的变量名和对象是分离的。变量名可以指向任意一个对象。从本质上,装饰器起到的就是这样一个重新指向变量名的作用(name binding),让同一个变量名指向一个新返回的可调用对象,从而达到修改可调用对象的目的。

与加工函数类似,我们可以使用装饰器加工类的方法。

 

如果我们有其他的类似函数,我们可以继续调用decorator来修饰函数,而不用重复修改函数或者增加新的封装。这样,我们就提高了程序的可重复利用性,并增加了程序的可读性。

 

含参的装饰器

在上面的装饰器调用中,比如@decorator,该装饰器默认它后面的函数是唯一的参数。装饰器的语法允许我们调用decorator时,提供其它参数,比如@decorator(a)。这样,就为装饰器的编写和使用提供了更大的灵活性。

# a new wrapper layer
def pre_str(pre=''):# old decoratordef decorator(F):def new_F(a, b):print(pre + "input", a, b)return F(a, b)return new_Freturn decorator# get square sum
@pre_str('^_^')
def square_sum(a, b):return a**2 + b**2# get square diff
@pre_str('T_T')
def square_diff(a, b):return a**2 - b**2print(square_sum(3, 4))
print(square_diff(3, 4))

上面的pre_str是允许参数的装饰器。它实际上是对原有装饰器的一个函数封装,并返回一个装饰器。我们可以将它理解为一个含有环境参量的闭包。当我们使用@pre_str('^_^')调用的时候,Python能够发现这一层的封装,并把参数传递到装饰器的环境中。该调用相当于:

square_sum = pre_str('^_^') (square_sum)

 

装饰类

在上面的例子中,装饰器接收一个函数,并返回一个函数,从而起到加工函数的效果。在Python 2.6以后,装饰器被拓展到类。一个装饰器可以接收一个类,并返回一个类,从而起到加工类的效果。

def decorator(aClass):class newClass:def __init__(self, age):self.total_display   = 0self.wrapped         = aClass(age)def display(self):self.total_display += 1print("total display", self.total_display)self.wrapped.display()return newClass@decorator
class Bird:def __init__(self, age):self.age = agedef display(self):print("My age is",self.age)eagleLord = Bird(5)
for i in range(3):eagleLord.display()

在decorator中,我们返回了一个新类newClass。在新类中,我们记录了原来类生成的对象(self.wrapped),并附加了新的属性total_display,用于记录调用display的次数。我们也同时更改了display方法。

通过修改,我们的Bird类可以显示调用display的次数了。

 

总结

装饰器的核心作用是name binding。这种语法是Python多编程范式的又一个体现。大部分Python用户都不怎么需要定义装饰器,但有可能会使用装饰器。鉴于装饰器在Python项目中的广泛使用,了解这一语法是非常有益的。

 

欢迎继续阅读“Python快速教程

 

转载于:https://www.cnblogs.com/vamei/archive/2013/02/16/2820212.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/494355.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android之多线程断点下载

本文主要包含多线程下载的一些简单demo,包括三部分 java实现 android实现 XUtils开源库实现 注意下载添加网络权限与SD卡读写权限 java实现多线程下载 public class MutileThreadDownload {/*** 线程的数量*/private static int threadCount 3;/*** 每个下载区块的大小*/…

量子计算赛道上的巨头拉锯战

来源:网易智能据国外媒体报道,长期以来量子计算机一直被吹捧为功能强大得令人难以置信的机器。相比于世界上现有的计算机,量子计算机能够以更快的速度解决极其复杂的计算问题。但目前还没有就开发量子计算机的最佳方式达成一致。最终谁将赢得…

【每日SQL打卡】​​​​​​​​​​​​​​​DAY 22丨平均售价【难度中等】​

【未来的你,会感谢今天努力的你】每日两题,一难一易,每天进步一点点,可能会直接导致一场面试的成功,或工作的轻松搞定,从而升职加薪迎娶白富美,加油小伙伴! 🍅举办场地&a…

Android之Intent深入

Android中的意图包含多种用法,本文主要包括以下内容 显式意图 隐匿意图 要求结果回传的意图 显式意图 :必须指定要激活的组件的完整包名和类名 (应用程序之间耦合在一起) 一般激活自己应用的组件的时候 采用显示意图 隐式意…

信通院AI白皮书:硬核干货一文打尽,从技术流派到应用趋势【附下载】

来源:智东西摘要:从产业发展的角度,分析AI技术现状、问题以及趋势,盘点智能语音、语义理解、计算机视觉等相关应用。自2016年AlphaGo击败李世石之后,人工智能(AI)这个再度翻红的科技热词已经在争…

【每日SQL打卡】​​​​​​​​​​​​​​​DAY 23丨向CEO汇报工作的人【难度中等】​

【未来的你,会感谢今天努力的你】每日两题,一难一易,每天进步一点点,可能会直接导致一场面试的成功,或工作的轻松搞定,从而升职加薪迎娶白富美,加油小伙伴! 🍅举办场地&a…

正则学习笔记

用途 字符匹配 语法 常用元字符 []    区间范围框 枚举值  [a-z0-9A-Z_] |    分枝条件或 \    特殊转义符(取消转义) \W [^A-Za-z0-9_] [\r\n] 换行符匹配 [\u4e00-\u9fa5] 汉字 [\s\S] 任意字符 限定符 贪婪匹配&…

Android之UI控件

本文主要包括以下内容 Spinner的使用 Gallery的使用 Spinner的使用 Spinner的实现过程是 1. 在xml文件中定义Spinner的控件 2. 在activity中获取Spinner控件 3. 定义Spinner下拉列表项数组并将下拉项的内容添加到这个数组中,通过这个数组建立一个下拉列表的适…

【每日SQL打卡】​​​​​​​​​​​​​​​DAY 23丨学生们参加各科测试的次数【难度简单】​

【未来的你,会感谢今天努力的你】每日两题,一难一易,每天进步一点点,可能会直接导致一场面试的成功,或工作的轻松搞定,从而升职加薪迎娶白富美,加油小伙伴! 🍅举办场地&a…

大脑如何判断该睡觉了?可能是这80种蛋白说了算

来源:科研圈撰文:Veronique Greenwood翻译:石云雷编辑:戚译引睡眠对于正常的学习和身体健康至关重要,但科学家们仍未完全了解睡眠在恢复大脑功能方面的作用和我们会感到困倦的原因。而通过对基因突变小鼠不寻常睡眠需求…

ImageLoader实现图片异步加载

ImageLoader是一个广泛使用的图片库,在向网络请求图片时,使用imageView和smartView常会产生outofmemory错误,这时ImageLoader可以起到很大的作用,主要有如下功能 一、功能特性: 多线程异步加载和显示图片(图片来源于…

【每日SQL打卡】​​​​​​​​​​​​​​​DAY 26丨广告效果【难度简单】​

【未来的你,会感谢今天努力的你】每日两题,一难一易,每天进步一点点,可能会直接导致一场面试的成功,或工作的轻松搞定,从而升职加薪迎娶白富美,加油小伙伴! 🍅举办场地&a…

AI芯片最新格局分析

来源:中金公司,作者黄乐平、何玫与杨俊杰AI 芯片设计是人工智能产业链的重要一环。 自 2017 年 5 月以来,各 AI 芯片厂商的新品竞相发布,经过一年多的发展,各环节分工逐渐明显。 AI 芯片的应用场景不再局限于云端&…

原理图学习笔记一

画个草图也挺过瘾 转载于:https://www.cnblogs.com/retacn-yue/archive/2013/02/17/3263137.html

【每日SQL打卡】​​​​​​​​​​​​​​​DAY 27丨每次访问的交易次数【难度困难-提前放出来】​

【未来的你,会感谢今天努力的你】每日两题,一难一易,每天进步一点点,可能会直接导致一场面试的成功,或工作的轻松搞定,从而升职加薪迎娶白富美,加油小伙伴! 🍅举办场地&a…

Android Studio安装与配置

谷歌已经停止支持eclipse开发android了,转向android studio是大势所趋,笔者由于电脑配置的原因, 以前迟迟不愿意向android studio,现如今因为开始学习material design,不得不转向android studio了, 费了一番功夫&…

材料界的魔术师:值得关注的10家超材料创业公司

来源:资本实验室超材料是具有人工设计的结构并呈现出天然材料所不具备的超常物理性质的人工复合结构或复合材料。典型的超材料有:“左手材料”、光子晶体、“超磁性材料”等。通俗地说,通过超材料技术,我们将能够摆脱来自自然界原…

ChildWindow在Open时旋转出现

在App.xaml中&#xff1a; <VisualState x:Name"Open"><Storyboard><DoubleAnimationUsingKeyFrames Storyboard.TargetProperty"(UIElement.Projection).(PlaneProjection.RotationY)" Storyboard.TargetName"ContentRoot">&…

【每日SQL打卡】​​​​​​​​​​​​​​​DAY 24丨不同国家的天气类型【难度简单】​

【未来的你&#xff0c;会感谢今天努力的你】每日两题&#xff0c;一难一易&#xff0c;每天进步一点点&#xff0c;可能会直接导致一场面试的成功&#xff0c;或工作的轻松搞定&#xff0c;从而升职加薪迎娶白富美&#xff0c;加油小伙伴&#xff01; &#x1f345;举办场地&a…

Android之ScrollView

1、ScrollView和HorizontalScrollView是为控件或者布局添加滚动条 2、上述两个控件只能有一个孩子&#xff0c;但是它并不是传统意义上的容器 3、上述两个控件可以互相嵌套 4、滚动条的位置现在的实验结果是&#xff1a;可以由layout_width和layout_height设定 5、ScrollV…