装饰器前奏:
一.定义:
1.装饰器本质是函数,语法都是用def去定义的
(函数的目的:他需要完成特定的功能)
2.装饰器的功能:就是装饰其他函数(就是为其他函数添加附加功能)
二.原则:
1. 不能修改被装饰的函数的源代码
2. 不能修改被修饰的函数的调用方式
三. 实现装饰器知识储备:
1.函数即“变量” (先定义,再调用)
2.高阶函数
3.嵌套函数
4.匿名函数 样式 (calc = lambde x:x*3 )
高阶函数 + 嵌套函数 =》 装饰器
1. 函数即“变量”
(1). python的内存机制
1
2
3
4
5
|
#变量 x = 1
#函数 def test():
pass
|
以上一个变量一个函数在内存中的表现形式如下图:
在python解释器中,有一个概念叫做引用基数,那什么叫引用基数呐,就是比方说,x=1,它会先在内存当中把1这个值试试在在的存放下来,这个x其实就是1的门牌号,也是对1的一次引用。python什么时候把这个1这个屋子清空呐?它会等到1所对应的门牌号都没有了,就会把1这里面的东西给清掉,这个也是python的内存回收机制,就是靠这种方式回收的。
(2). del清理
那我们用什么清理呐?用del去清理门牌号,就是对1的值引用的变量,del x就表示清理掉1对应的x的门牌号。如果x没有被del,则x永远不还被删除,除非程序结束了,不然永远不会被删除。del删除的不是1,只是把门牌号x删除了,只是定期刷新时,发现1没有被其他门牌号引用了,才会被清掉。
(3). 函数在内存的表现形式
我们先通过四个例子来解释一下:
①bar函数没有定义
1
2
3
4
5
6
7
8
9
10
11
12
|
#bar函数没有定义 def foo():
print ( "in the foo" )
bar()
foo() #输出 in the fooNameError: name 'bar' is not defined |
②bar函数在foo函数之后定义
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#bar函数在foo函数之后定义 def foo():
print ( "in the foo" )
bar()
def bar():
print ( "in the bar" )
foo() #输出 in the foo
in the bar
|
③bar函数是在foo函数之前定义
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# bar函数是在foo函数之前定义 def bar():
print ( "in the bar" )
def foo():
print ( "in the foo" )
bar()
foo() #输出 in the foo
in the bar
|
显然,两种写法效果是一样的,那我们来看看第四种情况。
④bar函数在foo函数调用之后声明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# bar函数在foo函数调用之后声明 def foo():
print ( "in the foo" )
bar()
foo() def bar():
print ( "in the bar" )
#输出 Traceback (most recent call last): in the foo
File "D:/PycharmProjects/pyhomework/day4/装饰器/函数即变量.py" , line 31 , in <module>
foo()
File "D:/PycharmProjects/pyhomework/day4/装饰器/函数即变量.py" , line 29 , in foo
bar()
NameError: name 'bar' is not defined #bar函数没有定义
|
2.高阶函数
满足下面条件之一就可以称为高阶函数:
a.把一个函数名当做实参传给另一个函数
b.返回值中包含函数名(调用函数体)
1、把一个函数名当做实参传给另外一个函数
作用:在不修改被装饰函数源代码的情况下为其添加功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
def bar():
time.sleep( 3 )
print ( "in the bar" )
def test1(func):
print (func)
start_time = time.time()
func() #run bar
stop_time = time.time()
print ( "the func run the is %s" % (stop_time - start_time))
#没有修改bar的代码 test1(bar) #把bar函数名当做实参传到test1中
#输出 <function bar at 0x0000000000A7D378 > #bar函数的内存地址
in the bar
the func run the is 2.9912972450256348
|
2、返回值中包括函数名
作用:不修改函数调用方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import time
def bar():
time.sleep( 3 )
print ( "in the bar" )
def test2(func):
print (func)
return func #返回函数的内存地址
#调用test2函数 bar = test2(bar)
bar() #没有bar函数改变调用方式
#输出 <function bar at 0x0000000000B6D378 > #打印bar函数的内存地址
in the bar
|