目录
闭包函数
什么是闭包
闭包:闭是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用)。闭包指的是:函数内部函数对外部作用域而非全局作用域的引用。
def outter(): x = 1 def inner(): print(x) # x = 1 return innerf = outter() # f = innerdef f2(): x = 2 f() # f() = inner()f2()
1
两种为函数传参的方式
方式一:使用参数的形式
def func(x): print(x)func(1)
1
方式二:包给函数
def outter(x): def inner(): print(x) return innerf = outter(1) # f = inner ,x = 1print(f)f()
.inner at 0x0000017E2A641048>1
闭包函数的应用
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域。
应用领域:延迟计算(原来我们是传参,现在我们是包起来)、爬虫领域。
import requestsdef outter(url): def get(): respond = requests.get(url) print(f'done:{url}') return getbaidu = outter('http://www.baidu.com') # baidu = getbaidu() # baidu() = get()taobao = outter('http://www.taobao.com') # taobao = gettaobao()
done:http://www.baidu.comdone:http://www.taobao.com
装饰器
无参装饰器
什么是装饰器
器指的是工具,而程序中的函数就是具备某一功能的工具,所以装饰器指的是为被装饰器对象添加额外功能。
注意:
- 装饰器本身其实是可以任意调用的对象
- 被装饰的对象也可以是任意可调用的对象
为什么要用装饰器
如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方发法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能是开放的。
装饰器的实现必须遵循两大原则:
- 不修改被装饰对象的源代码
- 不修改被装饰对象的调用方式
装饰器就是在遵循以上两个原则的前提下为被装饰对象添加新功能。
怎么用装饰器
# 改变调用方式import timedef index(): print('welcome to index') time.sleep(1)def time_count(func): start = time.time() func() # index() end = time.time() print(f'{func} time is {end - start}')time_count(index) # 改变了index的调用方式
welcome to indextime is 1.0003917217254639
# 包给函数—外包import timedef index(): print('welcome to index') time.sleep(1)def time_count(func): def wrapper(): start = time.time() func() # index() end = time.time() print(f'{func} time is {end - start}') return wrapperprint(index) #print('*'*20)index = time_count(index) # index = wrapperindex() # index() = wrapper()print('*'*20)print(index) # 地址与第一个打印不同# .wrapper at 0x0000017E2A8A00D0>
********************welcome to index time is 1.0003859996795654******************** .wrapper at 0x0000017E2A8A00D0>
完善装饰器
- 如果原始的index()有调用值,上述的wrapper()却没有,两者的返回值应该相同,我们需要同步原始函数有个返回值。
import timedef index(): print('welcome to index') time.sleep(1) return "I'm index"def time_count(func): def wrapper(): start = time.time() res = func() # res = index() = "I'm index" end = time.time() print(f'{func} time is {end - start}') return res return wrapperprint(index())print('*'*20)index = time_count(index)res = index()print(res)
welcome to indexI'm index********************welcome to indextime is 1.0053789615631104I'm index
- 如果原始的函数需要传参,那么我们之前的装饰器无法实现该功能的,那么只要给wrapper()传参即可。
import time def home(name): print(f'welcome {name} to home page') time.sleep(1) return name def time_count(func): def wrapper(*args,**kwargs): start = time.time() res = func(*args,**kwargs) end = time.time() print(f'{func} time is {end - start}') return res return wrapperhome = time_count(home) # home = wrapperres = home('william') res = wrapper('william')print(res)
welcome william to home pagetime is 1.0003857612609863william
装饰器语法糖
在被装饰的函数上方,单独写一行@装饰器名
# 上方函数用语法糖import time def time_count(func): def wrapper(*args,**kwargs): start = time.time() res = func(*args,**kwargs) end = time.time() print(f'{func} time is {end - start}') return res return wrapper@time_countdef home(name): print(f'welcome {name} to home page') time.sleep(1) return name@time_countdef index(): print('welcome to index') time.sleep(1) return "I'm index" print(index())print('*'*20)print(home('william'))
welcome to indextime is 1.0003869533538818I'm index********************welcome william to home page time is 1.0013864040374756william
装饰器模板
def deco(func): def wrapper(*args,**kwargs): res = func(*args,**kwargs) return res return wrapper
有参装饰器
无参装饰器只套了两层,下面是三层装饰器—有参装饰器。这个参数是装饰器的参数。
# 登陆注册(判断信息来源,'file'可以,其他不行)is_login_dict = {'username':None}def auth(origin): def login(func): def wrapper(*args,**kwargs): if origin == 'file': print('from file') if not is_login_dict.get('username'): username = input('please enter your username>>>').strip() print('login successfully') res = func(*args,**kwargs) is_login_dict['username'] = username return res else: res = func(*args,**kwargs) return res else: print('illegal original') return wrapper return login@auth('file')def shopping(): print('from shopping') @auth('mongodb')def withdraw(): print('from withdraw') @auth('file')def paying(): print('from paying') shopping() # 需要输入用户名print('*'*20)withdraw() #来源错误print('*'*20)paying() # 无需再次输入用户名
from fileplease enter your username>>>williamlogin successfullyfrom shopping********************illegal original********************from filefrom paying