目录
一、python的闭包
示例1:闭包
示例2:形成闭包的条件
示例3:形成闭包以后,闭包函数会得到一个非空的__closure__属性
示例4:赋值引用闭包和直接调用外函数的区别
二、装饰器
示例1:统计函数执行时间
示例2:写一个统计函数运行时间的装饰器
示例3:什么是装饰器
示例4:用装饰器实现权限控制
示例5:保留元数据
示例6:用类实现装饰器
示例7:装饰类
def outer(x):
a = 300
def inner():
print(f"两数之和{x + a}")
return inner
d = outer(10)
d()
变量解析原则:
LEGB 原则
local当前局部变量 enclosing function 闭包空间 global全局 buildins 内建模块
理论上来说,函数执行完了以后,变量a会释放
但是这个时候还有inner函数在引用他们,这个时候就形成了闭包
形成闭包条件:(缺一不可)
1、必须有一个内嵌函数
2、内函数必须引用外函数的变量
3、外函数必须返回内函数
def outer(x):
a = 300
def inner():
print(f"两数之和{x + a}")
return inner
d = outer(10)
d()
# 闭包形成后,闭包函数会得到一个非空的__closure__属性
print(dir(d))
print(d.__closure__)
E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/01、闭包.py
两数之和310
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
(, )
Process finished with exit code 0
| |
虽然代码一样,但是每次调用外函数都会重新执行,创建一个新的tmp_list和inner
匿名变量,都是统一放到匿名空间的,所以地址一样
tmp_list = []
def outer():
tmp_list = []
def inner(name):
tmp_list.append(1)
print(f"{name} -- {tmp_list}")
return inner
d1 = outer()
d2 = outer()
d1("d1")
d2("d2")
# 虽然代码一样,但是每次调用外函数都会重新执行,创建一个新的tmp_list和inner
print(id(d1), id(d2))
# 匿名变量,都是统一放到匿名空间的,所以地址一样
print(id(outer()), id(outer()))
E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/01、闭包.py
d1 -- [1]
d2 -- [1]
2138501753296 2138501753440
2138501753584 2138501753584
时间戳:
从1970年1月1日的0点0分0秒到现在所经历的秒数
import time
def func1():
time.sleep(2)
print("func1....")
# 时间戳
# 从1970年1月1日的0点0分0秒到现在所经历的秒数
t1 = time.time()
func1()
t2 = time.time()
print(f"函数执行时间{t2 - t1}")
E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/02、装饰器.py
func1....
函数执行时间2.0112464427948
@ :修饰符
import time
def runtime(func):
print("this is runtime")
def inner():
start = time.time()
func()
end = time.time()
print(f"函数执行花了{end - start}s")
return inner
@runtime # @修饰符去使用装饰器 # runtime(func2)
def func2():
time.sleep(2)
print("func2....")
E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/02、装饰器.py
this is runtime
func2....
函数执行花了2.0134215354919434s
装饰器是一种模式,它的本质是闭包,
他在不改变函数或者类的源代码的基础上
为函数或类添加功能
装饰器有什么用
• 你可以考虑在装饰器中置入通用功能的代码来降低程序复杂度。例如,可以用装饰器来:
• 引入日志
• 增加计时逻辑来检测性能
• 给函数加入事务的能力
• 权限控制
# 装饰器实现权限控制
def login_required(func):
def inner(*args, **kwargs):
if username == "root":
print("欢迎")
result = func(*args, **kwargs)
return result
else:
return "权限不够"
return inner
# 可以应用多个装饰器,但是要注意顺序
# 从最上面的装饰器的内涵式开始执行
@login_required
def add(a, b):
time.sleep(2)
return a + b
username = input("请输入用户名:")
result = add(1, 2)
print(result)
E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/02、装饰器.py
请输入用户名:root
欢迎
3
import time
def runtime(func):
# 保留传递进来的函数的元数据,将它的元数据赋值给inner
@functools.wraps(func)
def inner(*args, **kwargs): # 让装饰器更加通用
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"函数 {func.__name__} 执行花了:{end -start}s")
return result
return inner
#
# a = runtime("name")
# add = a(add)
@runtime # add = runtime(add)
def add(a, b):
print("this is add ")
time.sleep(1)
return a+b
add(1, 2)
E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/03、装饰器参数.py
this is add
函数 add 执行花了:1.0147972106933594s
import functools
import time
def deco(name):
def runtime(func):
#保留传递进来的函数的元数据,将它的元数据赋值给inner
@functools.wraps(func)
def inner(*args, **kwargs): #让装饰器更加通用
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"函数执行花了{end -start}s")
print(f"name is {name}")
return result
return inner
return runtime
# runtime = deco(name="sanle")
#func1 = runtime(func1)
@deco(name="sanle")
def func1():
time.sleep(3)
print("this is func1")
func1()
import time
class A:
def __init__(self, func):
self.func = func
def __call__(self, func):
def deco(*args, **kwargs):
start = time.time()
print("this is call")
result = func(*args, **kwargs)
end = time.time()
print(f"函数执行时间{end - start}")
return result
return deco
@A("name")
def func1():
time.sleep(2)
print("i am func1....")
func1()
def outer(cls):
def inner(*args, **kwargs):
print(f"class name is:{cls.__name__}")
return cls(*args, **kwargs)
return inner
@outer
class A:
def __init__(self, name):
self.name = name
print(type(A))
m = A("sc")
print(m.name)
E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/05、装饰类.py
class name is:A
sc