目录
示例3:形成闭包以后,闭包函数会得到一个非空的__closure__属性
- 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__']
- (
0x0000015CD0A9FE80: int object at 0x0000015CD09993B0>, | 0x0000015CD09417F0: int object at 0x0000015CBEE46A50>) | | -
- 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 'function'>
- class name is:A
- sc