装饰器介绍Python装饰器是程序开发中经常使用到的功能,熟练掌握装饰器会让你的编程思路更加广阔
要理解装饰器,首先要先理解:
1. 在 Python 中“函数是一等对象” 。即函数是一种特殊类型的变量,可以和其余变量一样,可以作为参数传递给函数,也可以作为返回值返回。Python 中的整数、字符串和字典等都是一等对象。
2. 函数装饰器在导入模块时立即执行,而被装饰的函数只在明确调用时运行。
装饰器实现
装饰器本质上是python函数,它可以使其他函数在不需要做代码变动的情况下增加新的功能,装饰器返回值也是一个函数对象。以下是一个简单的例子:
假设现在有一个函数sayHi,用来输出一句话
def sayHi():
print('Hello, World')
s = sayHi
s()输出:Hello, World
我想希望在不修改sayHi函数的情况下在其之前再输出一句话,这种在代码运行期间动态增加功能的方式,称之为“装饰器”。
本质上,装饰器就是一个返回函数的高阶函数我们可以这么写:
def sayName(func):
def inner():
print("I'm Yu")
return func
return inner()
def sayHi():
print('Hello, World')
s = sayName(sayHi)
s()输出:
I'm Yu
Hello, World
但代码美中不足的是,我们每次给sayHi增加功能都需要用到类似s = sayName(sayHi)这句话。
python为了简化这种情况,提供了一个语法糖“@”。简化上边的代码:
def sayName(func):
def inner():
print("I'm Yu")
return func()
return inner
@sayName
def sayHi():
print('Hello, World')
sayHi()输出:
I'm Yu
Hello, World
装饰器原理
以上代码中,首先,在装饰器函数sayName中,sayName需要接受一个参数func,在其内部又定义了一个inner函数,在inner函数中增加一句输出,并返回func对象,然后sayName函数返回内部函数inner,其实就是一个闭包函数。
接下来在sayHi上边增加一个@sayName,其意义就是在python解释器之行到此处时,会调用装饰器函数(sayName),并把被装饰得函数(sayHi)作为参数传入。此时的sayHi已经不是未加装饰时的函数了,而是指向sayName.inner函数地址。在接下来调用sayHi()时,其实就是调用sayName.inner。
有参函数装饰
之前的例子是对无参函数的装饰,如果装饰带参数的函数该如何处理?
def sayName(func):
def inner(name):
print("I'm Yu")
return func(name)
return inner
@sayName
def sayHi(name):
print('Hi,' + name)
sayHi('siri')输出:
I'm Yu
Hi,siri
两个装饰器装饰函数
这里测试两个装饰器装饰一个函数的结果:
def sayName(func):
print('name')
def inner():
print("I'm Yu")
return func()
return inner
def sayAge(func):
print('age')
def inner():
print("i'm 30")
return func()
return inner
@sayName
@sayAge
def sayHi():
print('Hello, World')
sayHi()输出:
age
name
I'm Yu
i'm 30
Hello, World
接下来分析输出这个结果的原因:
首先,python解释器执行到第一个装饰器@sayName,在接下来发现装饰器下边不是一个函数而是另一个装饰器,解释器会执行第二个的装饰器@sayAge,然后把sayHi函数传入装饰器,所以首先输出了“age”,当@sayAge装饰完成,此时的sayHi函数地址指向了sayAge.inner的地址,解释器会返回去执行@sayName装饰器来装饰新的sayHi,从而输出了“name”,接着函数当前指向sayName.inner会先输出“I'm Yu”,在这里返回的func()其实就是返回的sayAge.inner,所以在下面输出i'm 30,最后输出原本sayHi的“Hello, World”
有参装饰器
下边是装饰器带参数:
def now(time):
def sayName(func):
def inner(name):
print('现在是: %s' % time)
print("I'm Yu")
return func(name)
return inner
return sayName
@now('2016/10/30')
def sayHi(name):
print('Hello,' + name)
sayHi('siri')输出:
现在是: 2016/10/30
I'm Yu
Hello,siri
以上就是python装饰器的相关介绍