一、python闭包
1、生命周期
def outer():
a = 10
print(f"test {a}")
outer()
2、闭包要满足的条件
? 2.1、必须要有内嵌函数
? 2.2、内涵数必须要引用外函数的变量
? 2.3、外函数必须返回内函数
示例:
def outer(x):
a = 300
def inner():
print(x+a)
return inner
d = outer(100)
d()
print(dir(d))
#形成闭包之后,闭包函数就会得到一个非空的__closure__属性
print(outer.__closure__,d.__closure__)
3、用闭包实例化的对象 .虽然代码都一样,但是创建的对象是不一样的,每次调用外函数都会重新执行,创建一个新的tmp_list和inner
def outer():
tmp_list = []
def inner(name):
tmp_list.append(name)
print(tmp_list)
return inner
d1 = outer()
d1("d1")
d1('d1')
d2 = outer()
d2('d2')
d2("d2")
二、装饰器
1、装饰器的介绍
1.是一种程序设计模式,不改变函数或类的源代码基础上,添加额外功能
2.装饰器的本质就是闭包函数,它需要把一个callable(函数,类)对象作为参数传递进来
2、引出装饰器
#为了引出装饰器
import time
#时间戳:
从1970到现在所经历的秒数
def func1():
time.sleep(2)
print("func1.........")
def func2():
time.sleep(3)
print("func2.........")
start = time.time()
func1()
end = time.time()
print(f"func1执行花了{end - start }秒")
start = time.time()
func2()
end = time.time()
print(f"func2执行花了{end - start }秒")
3、统计运行时间的装饰器
#除了主功能之外还实现了其他功能
import time
def runtime(func):
def inner(*args,**kwargs):
start = time.time()
result = func(*args,**kwargs) #让装饰器更加通用
end = time.time()
print(f"执行函数花了{end - start}秒")
return result
return inner
# @ 修饰符,去使用装饰器
@runtime #func1 = runtime(func1)
def func1():
time.sleep(2)
print("func1.........")
return "sanchuang"
@runtime
def func2(a,b):
time.sleep(3)
print("func2.........")
print(f"fun2...{a}{b}")
result = func1()
print(result)
func2(1,2)
4、用装饰器实现权限控制
import functools
import time
def deco(name):
def runtime(func):
#保留传递进来的函数的原数据,将它的原数据赋值给inner
@functools.wraps(func)
def inner(*args,**kwargs):
if name=="root":
print("欢迎")
print(f"func name is {func.__name__}")
result = func(*args,**kwargs)
return result
else:
return "没有权限"
return inner
return runtime
username = input("请输入你的用户名:")
@deco(name=username)
def add(a,b):
time.sleep(3)
return a+b
print(add(1,2))
三、装饰器的应用
1、可以应用多个装饰器去装饰函数,但是要注意装饰器的执行顺序 2、添加额外功能:计时、权限控制、日志记录等 3、案例:
import functools
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"函数执行花了{end - start}s")
return result
return inner
def login_required(func):
username = input("请输入你的用户名:")
def inner(*args,**kwargs):
if username=='root':
print(f"欢迎执行{func.__name__}函数")
result = func(*args,**kwargs)
return result
else:
return "没有权限"
return inner
@login_required
@runtime
def add(a,b):
time.sleep(2)
return a+b
result = add(1,2)
print(result)
@login_required
@runtime
def add2(a,b):
time.sleep(3)
return a+b
result1 = add2(1,2)
print(result1)
四、带参数的装饰器
1、自身不传入参数的装饰器,使用两层函数定义 2、自身传入参数的装饰器,使用三层函数定义
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()
3、练习
?装饰器带参数,来验证用户是否有权限运行函数
运行add函数,运行前要判断有没有权限
? 判断一:用户名和密码是否正确 ---用户名错误或密码错误
? 判断二:用户名是否为root,只有root用户有权限 ----输出用户没有权限
? 用户名和密码 通过带参传入
import functools
import time
def deco(name):
def runtime(func):
#保留传递进来的函数的原数据,将它的原数据赋值给inner
@functools.wraps(func)
def inner(*args,**kwargs):
if name=="root":
print("欢迎")
print(f"func name is {func.__name__}")
result = func(*args,**kwargs)
return result
else:
return "没有权限"
return inner
return runtime
username = input("请输入你的用户名:")
@deco(name=username)
def add(a,b):
time.sleep(3)
return a+b
print(add(1,2))
五、属性包装 装饰器----property
property:把方法当作属性来使用
class Person():
_age = 2
@property #property本身会创建另外两个装饰器,@age.setter @age.deleter
def age(self):
return self._age
@age.setter
def age(self,num):
if 0< num <120:
self._age = num
else:
raise ValueError("年龄不在范围")
p = Person()
print(p.age)
p.age = 110
print(p.age)
六、用类去实现装饰器
1、不带参数的装饰器用类实现
import time
class runtime:
def __init__(self,func):
self.func = func
def __call__(self,*args,**kwargs):
start = time.time()
result = self.func(*args,**kwargs)
end = time.time()
print(f"运行函数{self.func.__name__}花费了{end - start}秒")
return result
@runtime
def func1(a,b):
print("this is func1......")
time.sleep(2)
return a+b
print(func1(1,2))
2、带参数的装饰器用类实现
import time
class runtime:
def __init__(self,name):
self.name = name
def __call__(self,func):
def deco(*args,**kwargs):
start = time.time()
result = func(*args,**kwargs)
end = time.time()
print(f"运行函数{func.__name__}花费了{end - start}秒")
return result
return deco
@runtime("name")
# a1 = runtime("name")
# func1 = a1(func1)
def func1():
time.sleep(2)
print("this is func1......")
func1()
七、装饰类
def outer(cls):
def inner(*args,**kwargs):
print(f"class name is:{cls.__name__}")
return cls(*args,**kwargs)
return inner
@outer # A = outer(A)
class A:
def __init__(self,name):
self.name = name
print(type(A))
m = A("sc")
print(m.name)
|