目录
python装饰器用来装饰其他函数的函数,即为其他函数添加特定功能或约束的函数(在Python中装饰器都是以@符号开头的)装饰器的两个原则:
1、装饰器不能修改被装饰函数的源码
2、装饰器不能修改被装饰函数的调用方式学习装饰器之前必须掌握的概念函数即变量高阶函数嵌套函数装饰器=高阶函数+嵌套函数
学习装饰器之前必须掌握的概念,接下来会详细讲解下面函数以及装饰器的演变过程
函数即变量
高阶函数
嵌套函数
装饰器=高阶函数+嵌套函数
1、函数即变量
-
函数名跟变量名一样,只是一个变量标识符,它指向函数定义对应的内存地址
def boo():
print("boo")
a = boo #函数名+()是对函数的调用,这种不加括号,是将变量a指向函数boo
a() #调用boo函数
print(a) #打印函数boo的地址
输出结果
boo
<function boo at 0x000001B178632E18>
-
在函数定义中去调用其他函数时,并不会立即调用该函数
-
在执行一个调用了其他函数的函数时,如果在内存中还没有找到被调用函数的定义,则程序会报错
函数foo()内部调用了boo函数。此时不会执行,在调用foo()才会执行,因为程序从上到下执行,所以如果定义的boo函数在调用foo()的下面,程序会报错。
def foo():
boo() #这里不会执行,只有调用foo才会执行
print("foo")
#foo() foo函数如果写在这里会报错,执行时找不到boo()函数
def boo():
print("boo")
a = boo #函数名+()是对函数的调用,这种不加括号,是将变量a指向函数boo
a()
boo()
foo()
输出结果
boo
boo
boo
foo
2、高阶函数
符合下列条件之一的函数就是高阶函数
-
接受函数名作为形参
-
返回值中包含函数名
定义一个foo函数,计算10000000以内的数字之和。定义一个height_fun函数,函数名作为形参,传进去输出在计算过程中的运行时间。
def foo():
sum = 0
for i in range(10000000):
sum = sum + i
print(sum)
import time
def height_fun(func):
start_time = time.time()
func()
end_time = time.time()
print("程序运行时间是{} ".format(end_time-start_time))
height_fun(foo) #把foo函数作为参数传递给height_fun
输出内容:
49999995000000
程序运行时间是0.2584867477416992
如果将在高阶函数中,把被装饰的函数返回,在调用装饰的函数,装饰的函数就多执行了一次。调用foo()时,height_fun里面的代码开始执行,执行完成后,又把foo函数返回,再次执行了一次。
def foo():
sum = 0
for i in range(10000000):
sum = sum + i
print(sum)
import time
def height_fun(func):
start_time = time.time()
func()
end_time = time.time()
print("程序运行时间是{} ".format(end_time-start_time))
return func
foo = height_fun(foo) #把foo函数作为参数传递给height_fun
foo()
输出结果
49999995000000
程序运行时间是0.2506873607635498
49999995000000
3、嵌套函数
通过def关键字定义在另一个函数中的函数叫做嵌套函数
def foo():
print("in foo")
def boo():
print("in boo")
foo()
运行结果:foo
4、装饰器
foo函数时计算10000000以内的数字之和,这里是想给他加一个装饰器,在计算输出结果的同时,也能输出运行时间。
首先先定义个被装饰的函数foo,装饰器相当于一个工厂,把要装饰的foo加工一下,在把它给送出去。在代码中体现就相当于把要被装饰的函数作为形参传到另一个函数里面,在返回被装饰后的函数,所以要在另一个函数里面嵌套一个新的函数。在里面封装要调用的代码、调用被装饰的函数,在返回一个新函数,为了不改变原来的调用函数方式,所以用foo指向装饰后的函数。装饰过程使用了高阶函数+嵌套函数
import time
def foo(): #被装饰的函数
sum = 0
for i in range(10000000):
sum += i
print(sum)
def timer(func): #高阶函数
def gf(): #定义一个嵌套函数
start_time = time.time()
func() #调用被装饰的函数
end_time = time.time()
print("函数运行时间{}".format(end_time-start_time))
return gf #返回装饰后的函数名
foo = timer(foo) #定义变量foo指向装饰后的函数
foo() #不改变原来的调用方式执行函数
可以在被装饰的函数上直接增加一个@timer,直接调用函数名,执行装饰后的函数。
import time
def timer(func): #高阶函数
def gf():
start_time = time.time()
func() #调用被装饰的函数
end_time = time.time()
print("函数运行时间{}".format(end_time-start_time))
return gf #返回装饰后的函数名
@timer #为了方便大家使用装饰器,python自定义的语法糖
def foo(): #被装饰的函数
sum = 0
for i in range(10000000):
sum += i
print(sum)
#foo = timer(foo)
foo() #不改变原来的调用方式执行函数
执行结果
49999995000000
函数运行时间0.24414944648742676
装饰器的编写步骤:
1、第一步:定义一个接受函数作为参数的高阶函数
2、第二步:在高阶函数中定义一个嵌套函数,在该嵌套函数中
-
封装想要添加的功能代码
-
调用作为参数传入的函数名
-
返回嵌套函数的函数名