一. 闭包
Python中的namespace
Python中通过提供 namespace 来实现重名函数/方法、变量等信息的识别,其一共有三种 namespace,分别为:
- local namespace: 作用范围为当前函数或者类方法
- global namespace: 作用范围为当前模块
- build-in namespace: 作用范围为所有模块
def outer():
a = 1
def inner():
# a = a + 1
print(a)
inner()
outer()
此时 a = a + 1 会报错。inner() 可以使用变量a, 但是此情况下无法修改a
在Python中创建一个闭包可以归结为以下三点:
- 闭包函数必须有内嵌函数
- 内嵌函数需要引用该嵌套函数上一级namespace中的变量
- 闭包函数必须返回内嵌函数
二. 装饰器:
# 装饰器的作用 python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能 # 装饰器原则: 开放封闭原则 对拓展时开放的, 对修改是封闭的
一个简单的装饰器:
import time
def func(): # 被装饰的函数
time.sleep(1)
print("老板好,同事好大家好")
def timmer(f): # 装饰器函数
def inner():
start = time.time()
f()
end = time.time()
print(end - start)
return inner
此时将函数func()作为参数传给timmer(),形成装饰效果
# 有参数和返回值时装饰器的模板
# 装饰器模板
def wrapper(f): # f 被装饰的名字
def inner(*args, **kwargs):
'''在被装饰函数前要做的事'''
ret = f(*args, **kwargs)
'''在被装饰函数后要做的事'''
return ret
return inner
使用:
@wrapper # 语法糖 装饰器函数名
def fun(a, b):
time.sleep(1)
print('老板好')
return '新年快乐'
三. 装饰器的进阶
1 funtools.warps 工具
from funtools import warps # 可以查看被装饰的函数的名字
def wrapper(f): # f 被装饰的名字
# 可以正常返回函数名,而不是inner函数名。
@warps(func)
def inner(*args, **kwargs):
"""在被装饰函数前要做的事"""
ret = f(*args, **kwargs)
"""在被装饰函数后要做的事"""
return ret
return inner
2,带参数的装饰器。可以控制多个装饰器使用
flag = True 设置标志位
# 再原有基础上使用一个函数嵌套装饰器
def timmer(flag):
def warpper(func):
# 当flag = True 时,装饰器生效。反之则不生效
def inner(*args, **kwargs):
if flag:
ret = func(*args, **kwargs)
return ret
else:
pass
return inner
return warpper
3.多个装饰器修饰同一个函数。执行顺序。
def wrapper1(f): # f 被装饰的名字
def inner(*args, **kwargs):
print('装饰器1调用前')
ret = f(*args, **kwargs)
print('装饰器1调用后')
return ret
return inner
def wrapper2(f): # f 被装饰的名字
def inner(*args, **kwargs):
print('装饰器2调用前')
ret = f(*args, **kwargs)
print('装饰器2调用后')
return ret
return inner
@wrapper1
@wrapper2
def func():
print('被装饰的函数')
func()
# 执行结果
'''
装饰器1调用前
装饰器2调用前
被装饰的函数
装饰器2调用后
装饰器1调用后
'''
4.基于装饰器的 单例模式
只是被修饰的对像从函数变为了类 。使用仍然相同
def singleton(cls):
instance = {}
def wrapper(*args, **kwargs):
if cls not in instance:
instance[cls] = cls(*args, **kwargs)
return instance[cls]
return wrapper
@singleton
class A:
pass
a1 = A()
a2 = A()
print(id(a1), id(a2))