Python 装饰器:拓展函数功能
在 Python程序中,通过使用装饰器可以给函数或类增强功能,并且还可以快速地给不同的函数或类插入相同的功能。从绝对意义上来说,装饰器是一种代码的实现方式。
一、创建装饰器
在Python程序中,可以使用装饰器给不同的函数或类插入相同的功能。与其他高级语言相比, Python语言不但简化了装饰器代码,而且可以快速地实现所需要的功能。同时,装饰器为函数或类又象在增加功能时变得十分透明对于同一函数来说,既可以添加简单的功能,也可以添加复杂功能,并且使用起来很灵活当调用被装饰的函数时,没有任何附加的东西,仍然像调用原函数或没有被装饰的函数一样。
要想在Python程序中使用装饰器,需要使用一个特殊的符号“@”来实现。在定义装饰器装饰函数或类时,使用“@装饰器名称”的形式将符号“@”放在函数或类的定义行之前。例如,有一个装饰器名称为“run_time",当需要在函数中使用装饰器功能时,可以使用如下形式定义这个函数。
@ run_time
def han_fun()
pass
在Python程序中使用装饰器后,例如上述代码定义的承数han_fun(可以只定义自己所需的功能,而装饰器所定义的功能会自动插入函数 han_fun()中,这样就可以节约大量具有相同功能的函数或类的代码。即使是不同目的或不同类的函数或类,也可以插入完全相同的功能。
要想用装饰器来装饰一个对象必须先定义这个装饰器。在 Python程序中,定义装饰器的格式与定义普通函数的格式完全一致,只不过装饰器函数的参数必须要有函数或类对象,然后在装饰器函数中重新定义一个新的函数或类,并且在其中执行某些功能前后或中间来使用被装饰的函数或类,最后返回这个新定义的函数或类。
二、使用装饰器修饰函数
在Python程序中,可以使用装饰器装饰函数。在使用装饰器装饰函数首先要定义一个装饰器,然后使用定义的装饰器来装饰这个函数。例如在下面的实例代;码中,演示了使用装饰器修饰函数的过程"
def zz(fun): #定义一个装饰器函数Zz()
def wrapper(*args, **bian): #定义一个包装器函数wrapper
print('比赛开始了...')
fun(*args, **bian) #使用被装饰函数
print('比赛结束!')
return wrapper #返回包装器函数wrapper()
@zz #装饰函数语句
def demo_decoration(x): #定义普通函数,被装饰器装饰
a = [] #定义空列表a
for i in range(x): #遍历x的值
a.append(i) #将i添加到列表末尾
print(a)
@zz
def hello(name): #定义普通函数hello(),被装饰器装饰
print('Hello,name')
if __name__== '__main__':
demo_decoration(5) #调用被装饰器装饰的函数demo decoration ()
print()
hello('中国跳水梦之队') #调用被装饰器装饰的函数hello()
在上述实例代码中,首先定义了一个装饰器函数zz(),此函数有一个可以使用的函数对象的参数 fun。然后定义了两个被装饰器装饰的普通函数,分别是demo_decoration( ) 和hello ( )。最后对被装饰的函数进行调用,当调用被装饰的函数时会发现。与调用普通函数没有任何区别。而在实现装饰器定义的内部,很明显又定义了一个内嵌的函数wrapper(),在这个内嵌的函数中执行了一些语句,也调用了被装饰的函数。最后返回这个内嵌函数,并代替了被装饰的函数,从而完成了装饰器的功能。执行后会发现在调用两个被装饰的函数前后都输出了相应的信息的功能,执行后会输出:
在上述实例中,其中装饰函数wapper()的参数是可变的,而被装饰函数demo_ decoration()和hello()的参数是固定的。
在Python程序中,当对带参数的函数进行装饰时,内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象。例如在下面的实例代码中,演示了使用装饰器装饰带参函数的过程:
def deco(func) : #定义装饰器函数deco()
def _deco(a,b): #定义函数deco()
print("在函数myfunc()之前被调用.")
ret = func(a,b)
print("在函数myfunc()之后被调用,结果是:%s" %ret)
return ret
return _deco
@deco
def myfunc(a, b): #定义函数myfunc()
print("函数myfunc(%s,%s)被调用!" %(a,b))
return a+b
myfunc(1,2)
myfunc(3,4)
执行后会输出:
三、使用装饰器修饰类
在Python程序中,也可以使用装饰器来装饰类。在使用装饰器装饰类时,需要先定义内嵌类中的函数,然后返回新类。例如在下面的实例代码中,演示了使用装饰器修饰类的过程:
def zz(myclass): #定义一个能够装饰类的装饰器zz
class InnerClass: #定义一个内嵌类InnerClass来代替被装饰的类
def __init__(self, z=0):
self.z = 0 #初始化属性z的值
self.wrapper =myclass () #实例化被装饰的类
def position(self):
self.wrapper.position()
print('z轴坐标:',self.z)
return InnerClass #返回新定义的类
@zz #使用装饰器
class coordination: #定义一个普通类coordination
def __init__(self,x=0,y=0):
self.x = x #初始化属性x
self.y = y #初始化属性y
def position(self): #定义普通方法position()
print('x轴坐标: ', self.x) # 显示x坐标
print('y轴坐标: ', self.y) #显示y坐标
if __name__ == '__main__': #当模块被直接运行时, 以下代码块会运行,当模块是被导入时不被运行
coor = coordination()
coor .position() #调用普通方法position()
在上述实例代码中,首先定义了一个能够装饰类的装饰器zz,然后在里面定义了一个内嵌类InnerClass来代替被装饰的类,并返回新的内嵌类。在实例化普通类时得到的是被装饰器装饰后的类。在运行程序后,因为原来定义的坐标类只包含平面坐标,而通过装饰器的装饰后则成为了可以表示立体坐标的三个坐标值,所以执行后会看到显示的坐标为立体坐标值(3个方向的值),执行后会输出: