20201203 装饰器之高阶函数

实现装饰器知识储备:
1. 函数即“变量”
2. 高阶函数
   a: 把一个函数名当做实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)
   b: 返回值中包含函数名(不修改函数的调用方式)
3. 嵌套函数

高阶函数 + 嵌套函数 ==> 装饰器
1-1
def bar():
    print('in the bar')

def test1(func):
    print(func)

test1(bar)
--->
<function bar at 0x0000019DE00C4828>
打印的是内存地址
1-1-2
>>> def bar():
...     pass
...
>>> bar
<function bar at 0x0000024FC0894948>
bar 是一个门牌号,帮助找到房间的位置而已。
所以,门牌号(内存地址)出来了

实际上 bar(),bar + 小括号,就是在基于内存地址,进行调用。
1-1-3
def bar():
    print('in the bar')

def test1(func):
    print(func)
    func()

test1(bar)
--->
<function bar at 0x0000024FC0894AF8>
in the bar

bar 就是一个门牌号,门牌号是一个映射的地址。
加小括号,就能运行。

bar传给 func后
相等于 func = bar 所以 func() 相当于 bar()

函数即变量
x=1
y=x 
bar是一个函数,可以像变量一样来回赋值。
1-1-4 
为什么要把 bar 传到 test1 中运行呢?直接运行不行吗?
def bar():
    print('in the bar')

def test1(func):
    print(func)
    func()
test1(bar)

bar()
--->
<function bar at 0x000001904E9A4828>
in the bar
in the bar

因为如果发生改动,比如
import time
def bar():
    time.sleep(3)
    print('in the bar')

def test1(func):
    start_time = time.time()
    func()      # run bar
    stop_time = time.time()
    print("the func run time is %s" %(stop_time-start_time))
test1(bar)
# 最后统计出的是bar的运行时间
1-1-5
装饰函数
原来就是  bar()
运行结果 in the bar 
现在写了高阶函数
import time
def bar():
    time.sleep(3)
    print('in the bar')

def test1(func):
    start_time = time.time()
    func()      # run bar   可以在不修改源代码的情况下,为源代码加上功能
    stop_time = time.time()
    print("the func run time is %s" %(stop_time-start_time))
test1(bar)
首先正常运行 bar 函数 
test1 是高阶函数,附加了计算 bar 函数 运行时间的功能。
--->
in the bar
the func run time is 3.0009982585906982
装饰器:
定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能
test1 是装饰器 要装饰别人的,bar 才是源代码
不同的是调用方式变了
2 返回值中可以包含函数名
import time
def bar():
    time.sleep(3)
    print('in the bar')
def test2(func):
    print(func)
    return func

test2(bar)
--->
<function bar at 0x000002355E45D8B8>
将首先打印 bar 函数的内存地址,所以
print(test2(bar))
--->
<function bar at 0x000002355E45D8B8>
<function bar at 0x000002355E45D8B8>
才可以看出效果,bar传给func,打印 func 返回内存地址,第二个打印值,就是 print 的运行结果
有内存地址就意味着,加上小括号就可以运行
2-1
import time
def bar():
    time.sleep(3)
    print('in the bar')
def test2(func):
    print(func)
    return func

test2(bar)
# 直接写 bar 相当于把内存地址传给 func 了
# 加上小括号相当于把 bar 的返回值传给 func 了,这样就不符合高阶函数的定义了
2-2
import time
def bar():
    time.sleep(3)
    print('in the bar')
def test2(func):
    print(func)
    return func

t=test2(bar)
print(t)
--->
<function bar at 0x00000207B962D8B8>
<function bar at 0x00000207B962D8B8>
怎么能让它有用呢??
t=test2(bar)
t() # run bar
--->
<function bar at 0x000001CBC36FD8B8>
in the bar
2-3 bar 只是一个门牌号,可以任意占用,覆盖之前的 bar
import time
def bar():
    time.sleep(3)
    print('in the bar')
def test2(func):
    print(func)
    return func

bar=test2(bar)
bar()        
# 这样能够运行吗?
--->
<function bar at 0x000002F49C12D8B8>
in the bar
相当于 test2 已经加上了 新功能,函数的调用方式没有改变

猜你喜欢

转载自blog.51cto.com/15149862/2679443