详解Python装饰器由浅入深

装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码。装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们以装饰函数为例子介绍其用法。要理解在Python中装饰器的原理,需要一步一步来。本文尽量描述得浅显易懂,从最基础的内容讲起。

(注:以下使用Python3.5.1环境)

一、Python的函数相关基础

第一,必须强调的是python是从上往下顺序执行的,而且碰到函数的定义代码块是不会立即执行它的,只有等到该函数被调用时,才会执行其内部的代码块。

def foo():
print("foo函数被运行了!")
如果就这么样,foo里的语句是不会被执行的。
程序只是简单的将定义代码块读入内存中。

再看看,顺序执行的例子:

def foo():
 print("我是上面的函数定义!")
def foo():
 print("我是下面的函数定义!")
foo()
运行结果:
我是下面的函数定义

可见,因为顺序执行的原因,下面的foo将上面的foo覆盖了。因此,在Python中代码的放置位置是有要求的,不能随意摆放,函数体要放在被调用的语句之前。

 其次,我们还要先搞清楚几样东西:函数名、函数体、返回值,函数的内存地址、函数名加括号、函数名被当作参数、函数名加括号被当作参数、返回函数名、返回函数名加括号。对于如下的函数:

 def foo():
 print("让我们干点啥!")
 return "ok"
 foo()  

   函数名:        foo

  函数体:        第1-3行

  返回值:        字符串“ok”    如果不显式给出return的对象,那么默认返回None

  函数的内存地址:    当函数体被读进内存后的保存位置,它由标识符即函数名foo引用,
                                                   也就是说foo指向的是函数体在内存内的保存位置。

  函数名加括号:       例如foo(),函数的调用方法,只有见到这个括号,程序会根据
                                                   函数名从内存中找到函数体,然后执行它

再看下面这个例子:

def outer(func):
 def inner():
 print("我是内层函数!")
 return inner
def foo():
 print("我是原始函数!")
outer(foo)
outer(foo())

在python中,一切都是对象,函数也不例外。因此可以将函数名,甚至函数名加括号进行调用的方式作为另一个函数的返回值。上面代码中,outer和foo是两个函数,outer(foo)表示将foo函数的函数名当做参数传递给outer函数并执行outer函数;outer(foo())表示将foo函数执行后的返回值当做参数传递给outer函数并执行outer函数,由于foo函数没有指定返回值,实际上它传递给了outer函数一个None。注意其中的差别,有没有括号是关键!

 同样,在outer函数内部,返回了一个inner,它是在outer函数内部定义的一个函数,注意,由于inner后面没有加括号,所以返回的是inner的函数体,实际上也就是inner这个名字,一个简单的引用而已。那么,如果outer函数返回的是inner()呢?现在你应该已经很清楚了,它会先执行inner函数的内容,然后返回个None给outer,outer再把这个None返回给调用它的对象。

 请记住,函数名、函数加括号可以被当做参数传递,也可以被当做返回值return,有没有括号是两个截然不同的意思!

二、装饰器的使用场景

装饰器通常用于在不改变原有函数代码和功能的情况下,为其添加额外的功能。比如在原函数执行前先执行点什么,在执行后执行点什么。

 让我们通过一个例子来看看,装饰器的使用场景和体现的设计模式。(抱歉的是我设计不出更好的场景,只能引用武大神的案例加以演绎)

 有一个大公司,下属的基础平台部负责内部应用程序及API的开发,有上百个业务部门负责不同的业务,他们各自调用基础平台部提供的不同函数处理自己的业务,情况如下: 

# 基础平台部门开发了上百个函数
def f1():
 print("业务部门1数据接口......")
def f2():
 print("业务部门2数据接口......")
def f3():
 print("业务部门3数据接口......")
def f100():
 print("业务部门100数据接口......")
#各部门分别调用
f1()
f2()
f3()
f100()

由于公司在创业初期,基础平台部开发这些函数时,由于各种原因,比如时间,比如考虑不周等等,没有为函数调用进行安全认证。现在,平台部主管决定弥补这个缺陷,于是:

  第一回,主管叫来了一个运维工程师,工程师跑上跑下逐个部门进行通知,让他们在代码里加上认证功能,然而,当天他被开除了。

 第二回:主管又叫来了一个运维工程师,工程师用shell写了个复杂的脚本,勉强实现了功能。但他很快就回去接着做运维了,不会开发的运维不是好运维....

 第三回:主管叫来了一个python自动化开发工程师,哥们是这么干的:只对基础平台的代码进行重构,让N个业务部门无需做任何修改。这哥们很快也被开了,连运维也没得做。  

def f1():
 #加入认证程序代码
 print("业务部门1数据接口......")
def f2():
 # 加入认证程序代码
 print("业务部门2数据接口......")
def f3():
 # 加入认证程序代码
 print("业务部门3数据接口......")
def f100():
 #加入认证程序代码
 print("业务部门100数据接口......")
#各部门分别调用
f1()
f2()
f3()
f100()

 第四回:主管又换了个 工程师,他是这么干的:定义个认证函数,原来其他的函数调用它,代码如下框。但是,主管依然不满意,不过这一次他解释了为什么。主管说:写代码要遵循开放封闭原则,虽然在这个原则主要是针对面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码内部不允许被修改,但外部可以被扩展,即:封闭:已实现的功能代码块;开放:对扩展开放。如果将开放封闭原则应用在上述需求中,那么就不允许在函数 f1 、f2、f3......f100的内部进行代码修改。遗憾的是,工程师没有漂亮的女朋友,所以很快也被开除了。

def login():
 print("认证成功!")
def f1():
 login()
 print("业务部门1数据接口......")
def f2():
 login()
 print("业务部门2数据接口......")
def f3():
 login()
 print("业务部门3数据接口......")
def f100():
 login()
 print("业务部门100数据接口......")
#各部门分别调用
f1()
f2()
f3()
f100()

第五回:已经没有时间让主管找别人来干这活了,他决定亲自上阵,并且打算在函数执行后再增加个日志功能。主管是这么想的:不会装饰器的主管不是好码农!要不为啥我能当主管,你只能被管呢?嘿嘿。他的代码如下:

#/usr/bin/env python
#coding:utf-8
def outer(func):
 def inner():
 print("认证成功!")
 result = func()
 print("日志添加成功")
 return result
 return inner
@outer
def f1():
 print("业务部门1数据接口......")
@outer
def f2():
 print("业务部门2数据接口......")
@outer
def f3():
 print("业务部门3数据接口......")
@outer
def f100():
 print("业务部门100数据接口......")
#各部门分别调用
f1()
f2()
f3()
f100()

对于上述代码,也是仅需对基础平台的代码进行拓展,就可以实现在其他部门调用函数 f1 f2 f3 f100 之前都进行认证操作,在操作结束后保存日志,并且其他业务部门无需他们自己的代码做任何修改,调用方式也不用变。“主管”写完代码后,觉得独乐了不如众乐乐,打算显摆一下,于是写了篇博客将过程进行了详细的说明。

 三、装饰器的内部原理、

 下面我们以f1函数为例进行说明:

 def outer(func):
 def inner():
 print("认证成功!")
 result = func()
 print("日志添加成功")
 return result
 return inner
@outer
def f1():
 print("业务部门1数据接口......")

运用我们在第一部分介绍的知识来分析一下上面这段代码:

  • 程序开始运行,从上往下编译,读到def outer(func):的时候,发现这是个“一等公民”->函数,于是把函数体加载到内存里,然后过。
  • 读到@outer的时候,程序被@这个语法糖吸引住了,知道这是个装饰器,按规矩要立即执行的,于是程序开始运行@后面那个名字outer所定义的函数。(相信没有人会愚蠢的将@outer写到别的位置,它只能放在被装饰的函数的上方最近处,不要空行。)
  • 程序返回到outer函数,开始执行装饰器的语法规则,这部分规则是定死的,是python的“法律”,不要问为什么。规则是:被装饰的函数的名字会被当作参数传递给装饰函数。装饰函数执行它自己内部的代码后,会将它的返回值赋值给被装饰的函数。 

如下图所示:

这里面需要注意的是:

  • @outer和@outer()有区别,没有括号时,outer函数依然会被执行,这和传统的用括号才能调用函数不同,需要特别注意!那么有括号呢?那是装饰器的高级用法了,以后会介绍。
  • 是f1这个函数名(而不是f1()这样被调用后)当做参数传递给装饰函数outer,也就是:func = f1,@outer等于outer(f1),实际上传递了f1的函数体,而不是执行f1后的返回值。
  • outer函数return的是inner这个函数名,而不是inner()这样被调用后的返回值。

如果你对第一部分函数的基础知识有清晰的了解,那么上面的内容你应该很容易理解。

 4. 程序开始执行outer函数内部的内容,一开始它又碰到了一个函数,很绕是吧?当然,你可以在 inner函数前后安排点别的代码,但它们不是重点,而且有点小麻烦,下面会解释。inner函数定义块被程序观察到后不会立刻执行,而是读入内存中(这是潜规则)。

 5. 再往下,碰到return inner,返回值是个函数名,并且这个函数名会被赋值给f1这个被装饰的函数,也就是f1 = inner。根据前面的知识,我们知道,此时f1函数被新的函数inner覆盖了(实际上是f1这个函数名更改成指向inner这个函数名指向的函数体内存地址,f1不再指向它原来的函数体的内存地址),再往后调用f1的时候将执行inner函数内的代码,而不是先前的函数体。那么先前的函数体去哪了?还记得我们将f1当做参数传递给func这个形参么?func这个变量保存了老的函数在内存中的地址,通过它就可以执行 老的函数体,你能在inner函数里看到result = func()这句代码,它就是这么干的!

 6.接下来,还没有结束。当业务部门,依然通过f1()的方式调用f1函数时,执行的就不再是老的f1函数的代码,而是inner函数的代码。在本例中,它首先会打印个“认证成功”的提示,很显然你可以换成任意的代码,这只是个示例;然后,它会执行func函数并将返回值赋值个变量result,这个func函数就是老的f1函数;接着,它又打印了“日志保存”的提示,这也只是个示例,可以换成任何你想要的;最后返回result这个变量。我们在业务部门的代码上可以用 r = f1()的方式接受result的值。

 7.以上流程走完后,你应该看出来了,在没有对业务部门的代码和接口调用方式做任何修改的同时,也没有对基础平台部原有的代码做内部修改,仅仅是添加了一个装饰函数,就实现了我们的需求,在函数调用前先认证,调用后写入日志。这就是装饰器的最大作用。

 问题:那么为什么我们要搞一个outer函数一个inner函数这么复杂呢?一层函数不行吗?

 答:请注意,@outer这句代码在程序执行到这里的时候就会自动执行outer函数内部的代码,如果不封装一下,在业务部门还未进行调用的时候,就执行了些什么,这和初衷有点不符。当然,如果你对这个有需求也不是不行。请看下面的例子,它只有一层函数。

def outer(func):
 print("认证成功!")
 result = func()
 print("日志添加成功")
 return result
@outer
def f1():
 print("业务部门1数据接口......")
# 业务部门并没有开始执行f1函数
执行结果:
认证成功!
业务部门1数据接口......
日志添加成功

看到没?我只是定义好了函数,业务部门还没有调用f1函数呢,程序就把工作全做了。这就是封装一层函数的原因。

四、装饰器的参数传递

细心的朋友可能已经发现了,上面的例子中,f1函数没有参数,在实际情况中肯定会需要参数的,那参数怎么传递的呢?

 一个参数的情况:

def outer(func):
 def inner(username):
 print("认证成功!")
 result = func(username)
 print("日志添加成功")
 return result
 return inner
@outer
def f1(name):
print("%s 正在连接业务部门1数据接口......"%name)
# 调用方法
f1("jack")

在inner函数的定义部分也加上一个参数,调用func函数的时候传递这个参数,很好理解吧?可问题又来了,那么另外一个部门调用的f2有2个参数呢?f3有3个参数呢?你怎么传递?

很简单,我们有*args和**kwargs嘛!号称“万能参数”!简单修改一下上面的代码:

def outer(func):
 def inner(*args,**kwargs):
 print("认证成功!")
 result = func(*args,**kwargs)
 print("日志添加成功")
 return result
 return inner
@outer
def f1(name,age):
 print("%s 正在连接业务部门1数据接口......"%name)
# 调用方法
f1("jack",18)

五、更进一步的思考

 一个函数可以被多个函数装饰吗?可以的!看下面的例子!  

def outer1(func):
 def inner(*args,**kwargs):
 print("认证成功!")
 result = func(*args,**kwargs)
 print("日志添加成功")
 return result
 return inner
def outer2(func):
 def inner(*args,**kwargs):
 print("一条欢迎信息。。。")
 result = func(*args,**kwargs)
 print("一条欢送信息。。。")
 return result
 return inner
 @outer1
@outer2
def f1(name,age):
 print("%s 正在连接业务部门1数据接口......"%name)
# 调用方法
f1("jack",18)
执行结果:
认证成功!
一条欢迎信息。。。
jack 正在连接业务部门1数据接口......
一条欢送信息。。。
日志添加成功

更进一步的,装饰器自己可以有参数吗?可以的!看下面的例子:

# 认证函数
def auth(request,kargs):
 print("认证成功!")
# 日志函数
def log(request,kargs):
 print("日志添加成功")
# 装饰器函数。接收两个参数,这两个参数应该是某个函数的名字。
def Filter(auth_func,log_func):
 # 第一层封装,f1函数实际上被传递给了main_fuc这个参数
 def outer(main_func):
 # 第二层封装,auth和log函数的参数值被传递到了这里
 def wrapper(request,kargs):
 # 下面代码的判断逻辑不重要,重要的是参数的引用和返回值
 before_result = auth(request,kargs)
 if(before_result != None):
 return before_result;
 main_result = main_func(request,kargs)
 if(main_result != None):
 return main_result;
 after_result = log(request,kargs)
 if(after_result != None):
 return after_result;
 return wrapper
 return outer
# 注意了,这里的装饰器函数有参数哦,它的意思是先执行filter函数
# 然后将filter函数的返回值作为装饰器函数的名字返回到这里,所以,
# 其实这里,Filter(auth,log) = outer , @Filter(auth,log) = @outer
@Filter(auth,log)
def f1(name,age):
 print("%s 正在连接业务部门1数据接口......"%name)
# 调用方法
f1("jack",18)
运行结果:
认证成功!
jack 正在连接业务部门1数据接口......
日志添加成功

又绕晕了?其实你可以这么理解,先执行Filter函数,获得它的返回值outer,再执行@outer装饰器语法。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我们!

(0)

相关推荐

  • 深入理解Python中装饰器的用法

    因为函数或类都是对象,它们也能被四处传递.它们又是可变对象,可以被更改.在函数或类对象创建后但绑定到名字前更改之的行为为装饰(decorator). "装饰器"后隐藏了两种意思--一是函数起了装饰作用,例如,执行真正的工作,另一个是依附于装饰器语法的表达式,例如,at符号和装饰函数的名称. 函数可以通过函数装饰器语法装饰: @decorator # ② def function(): # ① pass 函数以标准方式定义.① 以@做为定义为装饰器函数前缀的表达式②.在 @ 后的部分必须

  • Python 装饰器深入理解

    讲 Python 装饰器前,我想先举个例子,虽有点污,但跟装饰器这个话题很贴切. 每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个办法就是把内裤改造一下,让它变得更厚更长,这样一来,它不仅有遮羞功能,还能提供保暖,不过有个问题,这个内裤被我们改造成了长裤后,虽然还有遮羞功能,但本质上它不再是一条真正的内裤了.于是聪明的人们发明长裤,在不影响内裤的前提下,直接把长裤套在了内裤外面,这样内裤还是内裤,有了长裤后宝宝再也不冷了.装饰器就像我们这里说的长裤,在不

  • 详解Python中最难理解的点-装饰器

    本文将带领大家由浅入深的去窥探一下,这个装饰器到底是何方神圣,看完本篇,装饰器就再也不是难点了. 一.什么是装饰器 网上有人是这么评价装饰器的,我觉得写的很有趣,比喻的很形象 每个人都有的内裤主要是用来遮羞,但是到了冬天它没法为我们防风御寒,肿木办? 我们想到的一个办法就是把内裤改造一下,让它变得更厚更长,这样一来,它不仅有遮羞功能,还能提供保暖,不过有个问题,这个内裤被我们改造成了长裤后,虽然还有遮羞功能,但本质上它不再是一条真正的内裤了.于是聪明的人们发明长裤 在不影响内裤的前提下,直接把长

  • Python的装饰器用法学习笔记

    在python中常看到在定义函数是使用@func. 这就是装饰器, 装饰器是把一个函数作为参数的函数,常常用于扩展已有函数,即不改变当前函数状态下增加功能. def run(): print "I'm run." 我有这么一个函数, 我想知道这个函数什么时候开始什么时候结束. 我应该这么写 def run(): print time.ctime() print "I'm run." print time.ctime() 但是如果不允许修改函数的话就需要装饰器了 de

  • 老生常谈Python进阶之装饰器

    函数也是对象 要理解Python装饰器,首先要明白在Python中,函数也是一种对象,因此可以把定义函数时的函数名看作是函数对象的一个引用.既然是引用,因此可以将函数赋值给一个变量,也可以把函数作为一个参数传递或返回.同时,函数体中也可以再定义函数. 装饰器本质 可以通过编写一个纯函数的例子来还原装饰器所要做的事. def decorator(func): def wrap(): print("Doing someting before executing func()") func(

  • 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)) 在拥有了基本的数学功能之后,我们可能想为函数增加其它的功能,比如打印输入.我们

  • 深入理解Python装饰器

    装饰器简介: 装饰器(decorator)是一种高级Python语法.装饰器可以对一个函数.方法或者类进行加工.在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果.相对于其它方式,装饰器语法简单,代码可读性高.因此,装饰器在Python项目中有广泛的应用. 装饰器最早在Python 2.5中出现,它最初被用于加工函数和方法这样的可调用对象(callable object,这样的对象定义有__call__方法).在Python 2

  • python装饰器初探(推荐)

    一.含有一个装饰器 #encoding: utf-8 ############含有一个装饰器######### def outer(func): def inner(*args, **kwargs):#要装饰f1(),这里用这俩形式参数,可以接受任意个参数,不管f1定义几个参数 print "1" r = func(*args, **kwargs)#这里要用func,不要用f1 print "2" return r return inner @outer #这里ou

  • 深入学习Python中的装饰器使用

    装饰器 vs 装饰器模式 首先,大家需要明白的是使用装饰器这个词可能会有不少让大家担忧的地方,因为它很容易和设计模式这本书里面的装饰器模式发生混淆.曾经一度考虑给这个新的功能取一些其它的术语名称,但是装饰器最终还是胜出了. 的确,你可以使用python装饰器来实现装饰器模式,但这绝对是它很小的一部分功能,有点暴殄天物.对于python装饰器,我觉得它是最接近宏的存在. 宏的历史 宏有有着非常悠久的历史,不过大多数人可能会有使用C语言预处理宏的经验.但是,对于C语言里的宏来说,它存在一些问题,(1

  • 详解Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们以装饰函数为例子介绍其用法.要理解在Python中装饰器的原理,需要一步一步来.本文尽量描述得浅显易懂,从最基础的内容讲起. (注:以下使用Python3.5.1环境) 一.Python的函数相关基础 第一,必须强调的是python是从上往下顺序执行的,而且碰到函数的定义代码块是不会立即执行它的,只

  • 实例详解Python装饰器与闭包

    闭包是Python装饰器的基础.要理解闭包,先要了解Python中的变量作用域规则. 变量作用域规则 首先,在函数中是能访问全局变量的: >>> a = 'global var' >>> def foo(): print(a) >>> foo() global var 然后,在一个嵌套函数中,内层函数能够访问在外层函数中定义的局部变量: >>> def foo(): a = 'free var' def bar(): print(a)

  • 详解Python装饰器

    1. 定义 本质是函数,用来装饰其他函数,为其他函数添加附加功能 2. 原则 a. 不能修改被装饰函数的源代码 b. 不能修改被装饰的函数的调用方式 3. 实现装饰器知识储备 a. 函数就是变量 b. 高阶函数     i. 把一个函数当作实参传给另外一个函数,在不修改被装饰函数源代码情况下为其添加功能     ii. 返回值中包含函数名, 不修改函数的调用方式 c. 嵌套函数 高阶函数+嵌套函数==>装饰器 # Author: Lockegogo user, passwd = 'LK', '1

  • 详解Python装饰器 给你的咖啡加点料

    一.函数回顾 1.在python中函数是一等公民,函数也是对象.我们可以把函数赋予变量. def make_cofe(type): print('获得一杯 : {}'.format(type)) ​ get_cofe = make_cofe get_cofe('咖啡') ​ ####输出##### 获得一杯 : 咖啡 这个例子中,我们把函数make_cofe 赋予了变量 get_cofe,这样之后你调用 get_cofe,就相当于是调用函数 make_cofe(). 2.把函数当作参数,传入另一

  • 详解Python装饰器的四种定义形式

    目录 前言 用函数装饰函数 用函数装饰一个类 用类定义装饰器,然后装饰一个函数 用类定义装饰器,然后装饰一个类 小结 前言 装饰器(decorator)在Python框架中扮演着重要角色,是Python中实现切面编程(AOP)的重要手段. aspect-oriented programming (AOP) ,在不改变代码自身的前提下增加程序功能 不改变代码自身,但需要在函数和类头上加一个标注(annotation),这个标注在Python里叫装饰器,在java里叫注解.在Python里,一共有四

  • 详解Python 装饰器执行顺序迷思

    探究多个装饰器执行顺序 装饰器是Python用于封装函数或代码的工具,网上可以搜到很多文章可以学习,我在这里要讨论的是多个装饰器执行顺序的一个迷思. 疑问 大部分涉及多个装饰器装饰的函数调用顺序时都会说明它们是自上而下的,比如下面这个例子: def decorator_a(func): print 'Get in decorator_a' def inner_a(*args, **kwargs): print 'Get in inner_a' return func(*args, **kwarg

  • 详解利用装饰器扩展Python计时器

    目录 介绍 理解 Python 中的装饰器 创建 Python 定时器装饰器 使用 Python 定时器装饰器 Python 计时器代码 其他 Python 定时器函数 使用替代 Python 计时器函数 估计运行时间timeit 使用 Profiler 查找代码中的Bottlenecks 总结 介绍 在本文中,云朵君将和大家一起了解装饰器的工作原理,如何将我们之前定义的定时器类 Timer 扩展为装饰器,以及如何简化计时功能.最后对 Python 定时器系列文章做个小结. 这是我们手把手教你实

  • 详解Python装饰器之@property

    一.property() 函数讲解 了解 @property 装饰器之前,我们首先要了解内置函数的 property(). class property(fget=None, fset=None, fdel=None, doc=None) 描述: 返回 property 属性. 参数说明: fget -- 获取属性值的函数. fset -- 设置属性值的函数. fdel -- 删除属性值函数. doc -- property 属性的文档字符串,如果没有给出 doc,则该 property 将拷贝

  • Python装饰器(decorator)定义与用法详解

    本文实例讲述了Python装饰器(decorator)定义与用法.分享给大家供大家参考,具体如下: 什么是装饰器(decorator) 简单来说,可以把装饰器理解为一个包装函数的函数,它一般将传入的函数或者是类做一定的处理,返回修改之后的对象.所以,我们能够在不修改原函数的基础上,在执行原函数前后执行别的代码.比较常用的场景有日志插入,事务处理等. 装饰器 最简单的函数,返回两个数的和 def calc_add(a, b): return a + b calc_add(1, 2) 但是现在又有新

  • 基于Python 装饰器装饰类中的方法实例

    title: Python 装饰器装饰类中的方法 comments: true date: 2017-04-17 20:44:31 tags: ['Python', 'Decorate'] category: ['Python'] --- 目前在中文网上能搜索到的绝大部分关于装饰器的教程,都在讲如何装饰一个普通的函数.本文介绍如何使用Python的装饰器装饰一个类的方法,同时在装饰器函数中调用类里面的其他方法.本文以捕获一个方法的异常为例来进行说明. 有一个类Test, 它的结构如下: clas

随机推荐