博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
闭包函数 装饰器
阅读量:5115 次
发布时间:2019-06-13

本文共 7229 字,大约阅读时间需要 24 分钟。

什么是闭包函数

  闭:指的是闭包函数数定义在一个函数内部的函数

  包:该内部函数包含对外城函数作用域名字的引用

  需要结合函数对象的概念将闭包函数返回到全局作用域去使用,从而打破函数层级的限制

为什么要用闭包函数

  闭包函数提供了一种为函数体传值的解决方案

如何用闭包函数

# 为函数体传值的方式一:参数# def func(x,y):#     print(x+y)## func(1,2)          3# 为函数体传值的方式二:闭包def outter(x,y):    # x=1    # y=2    def func():        print(x+y)    return funcf=outter(1,2) f()                          3f()                          3f()                          3 解决方案一:参数# def get(url):#     response=requests.get(url)#     if response.status_code == 200:#         print(len(response.text))# get('https://www.baidu.com')# get('https://www.baidu.com')# get('https://www.baidu.com')# get('https://www.tmall.com')# get('https://www.tmall.com')# url1='https://www.baidu.com'# url2='https://www.tmall.com'## get(url1)# get(url1)# get(url1)## get(url2)# get(url2)# get(url2) 解决方案二:闭包# def outter(url):#     # url='https://www.baidu.com'#     def get():#         response=requests.get(url)#         if response.status_code == 200:#             print(len(response.text))#     return get## baidu=outter('https://www.baidu.com')# baidu()# baidu()# baidu()## tmall=outter('https://www.tmall.com')# tmall()# tmall()# tmall()

装饰器   

  器:指的是具备某一功能的工具

  装饰:值的是为了被装饰器对象添加新的功能

  装饰器就是用来为了被装饰对象添加新功能的工具

   注意: 装饰器本身可以是任意可调用对象,被装饰器的对象也可以是任意可调用对象

为什么用装饰器

  开放封闭原则:封闭值的是对修改源代码封闭,对扩展功能开放

  装饰器的实现必须遵循量大原则:

    1 不修改被装饰对象的源代码

    2不修改被装饰对象的调用方式

  装饰器的目标:就是在遵循1和2原则的前提下为被装饰对象添加上新功能

import timedef index():    print('welcome to index page')    time.sleep(3)def outter(func): # func=最原始那个index的内存地址    def wrapper():        start=time.time()        func() #最原始的那个index的内存地址()        stop=time.time()        print('run time is %s' %(stop - start))    return wrapperindex=outter(index) #index=outter(最原始那个index的内存地址) #index=wrapper的内存地址index() #wrapper的内存地址()

装饰器的语法糖:在被装饰器对象正上方单独一行写@装饰器的名字

  python解释器一旦运行到@装饰器的名字,就会调用装饰器然后将被装饰函数的内存地址当做参数传递给装饰器,最终将装饰器调用的结果赋值给原函数名 (原函数名=@外层函数运行结果返回值(二层函数名:就是加新功能的新函数名))

  面试——解释@语法的时候自下而上运行

      而执行装饰器的时候自上而下

 
# def o1(func): #     def inner(*args, **kwargs): #         print('o1 ------------')  # 1 #         result = func(*args, **kwargs) #         print('o1 ============')  # 5 #         return result #     return inner # # def o2(func): #     def inner(*args, **kwargs): #         print('o2 ------------')  # 2 #         result = func(*args, **kwargs) #         print('o2 ============')  # 4 #         return result #     return inner # @o1 # @o2 # def fn2(): #     print('fn2 ============')  # 3 # fn2()  # 函数调用位置 # # 执行流程:函数调用位置 => o1装饰器inner => o2装饰器inner => 本体fn2 # #  => 回到o2装饰器inner =>回到o1装饰器inner => 回到函数调用位置
import time## def timmer(func): #func=最原始那个home函数的内地址#     def wrapper(*args,**kwargs): #args=('egon',) kwargs={}#         start=time.time()#         res=func(*args,**kwargs) #最原始那个home函数的内地址('egon')#         stop=time.time()#         print('run time is %s' %(stop - start))#         return res#     return wrapper## @timmer #index=timmer(index)# def index():#     print('welcome to index page')#     time.sleep(3)
import time def timmer(func):  #func=wrapper2     def wrapper1(*args,**kwargs):         start=time.time()         res=func(*args,**kwargs)  #res=wrapper2(*args,**kwargs)         stop=time.time()         print('run time is %s' %(stop - start))         return res     return wrapper1 def auth(func): #func=最原始的那个index的内存地址     def wrapper2(*args,**kwargs):         inp_user = input('please input your username: ').strip()         inp_pwd = input('please input your password: ').strip()         if inp_user == 'egon' and inp_pwd == '123':             print('login successfull')             res=func(*args,**kwargs) # 调用最原始的那个/也就是被装饰的那个函数             return res         else:             print('username or password error')     return wrapper2 # 解释@语法的时候是自下而上运行 # 而执行装饰器内的那个wrapper函数时的是自上而下 @timmer # index=timmer(wrapper2) #index=wrapper1 @auth # index=auth(最原始的那个index的内存地址) #index=wrapper2 def index():     print('welcome to index page')     time.sleep(3) index() #wrapper1()
 

装饰器模板

import time def outer(func):   def wrapper(*args,**kwargs):     #在调用函数前增加新功能     res=func(*args,**kwargs) #调用被装饰的 也就是最原始的那个函数     #在调用函数后加功能     return res   return wrapper @outter  #index=outer(index) #index =wrapper def index():   print ('welcome to index page')   time.sleep(3) index() ef wrap(fn):    def inner(*args,**kwargs):        print('前面增功能')        result=fn(*args,**kwargs)        print('后面增功能')        return result    return inner@wrapdef fn1():    print('fn1的原功能')@wrapdef fn2(a,b):    print('fn2的原有功能')@wrapdef fn3():    print('fn3的原有功能')    return True@wrapdef fn4(a,*,x):    print('fn4原有功能')    return Truefn1()fn2(10,29)fn1()fn4(19,x=7)
def wrap(func):  # 原版fn4     def inner(*args, **kwargs):  # 新版fn4         pass  # 新功能         if args[0] == 10:             print('传入的a值是10')         else:             print('传入的a值不是10')         result = func(*args, **kwargs)  # 原功能         pass  # 新功能         return result     return inner @wrap  # fn4 = wrap(fn4) def fn4(a, b, c, *, x, y, z):  # 本尊     pass # fn4 = wrap(fn4)  # 新版fn4(升级版fn4) fn4(1, 2, 3, x=10, y=20, z=30)
认证功能的装饰器import timedef auth(func):    def wrapper(*args,**kwargs):        inp_user = input('please input your username: ').strip()        inp_pwd = input('please input your password: ').strip()        if inp_user == 'egon' and inp_pwd == '123':            print('login successfull')            res=func(*args,**kwargs) # 调用最原始的那个/也就是被装饰的那个函数            return res        else:            print('username or password error')    return wrapper@auth # index=auth(index) #index=wrapperdef index():    print('welcome to index page')    time.sleep(3)index() #wrapper()
is_login = False  # 登录状态 def login():     usr = input('usr: ')     if not (len(usr) >= 3 and usr.isalpha()):         print('账号验证失败')         return False     pwd = input('pwd: ')     if usr == 'abc' and pwd =='123qwe':         print('登录成功')         is_login = True     else:         print('登录失败')         is_login = False # 完成一个登录状态校验的装饰器 def check_login(fn):     def inner(*args, **kwargs):         # 查看个人主页或销售功能前:如果没有登录先登录,反之可以进入其功能         if is_login != True:             print('你未登录')             login()         # 查看个人主页或销售         result = fn(*args, **kwargs)         return result     return inner # 查看个人主页功能 @check_login def home():     print('个人主页') # 销售功能 @check_login def sell():     print('可以销售') home()

 带参装饰器  函数嵌套3层 

def wrap(var):    def outer(func):  # outer的参数是固定的,就是被装饰的函数对象        print(var)        def inner(*args, **kwargs):            print(111111111111111)            func(*args, **kwargs)            print(333333333333333)        return inner    return outer# 1.调用wrap返回outer# 2.调用outer传入fn3返回inner给fn3@wrap(000)  # wrap(000) => outer    => @outer   =>fn3 = outer(fn3)def fn3():    print(222222222222222)# 3.调用fn3就是调用inner,在inner内部调用原fn3fn3() 有参装饰器的参数写在语法糖()中
@wraps装饰器应该加到装饰器最内层的函数上 是为了函数的注释说明
def deco(func):    @wraps(func)    def wrapper(*args, **kwargs):        res = func(*args, **kwargs)        return res    # wrapper.__name__=func.__name__    # wrapper.__doc__=func.__doc__    return wrapper@deco #index=deco(index) #index=wrapper函数的内存地址def index():    """    index 功能    """    print('welcome to index page')    time.sleep(3)

 

转载于:https://www.cnblogs.com/lakei/p/10643388.html

你可能感兴趣的文章
Html5 离线页面缓存
查看>>
《绿色·精简·性感·迷你版》易语言,小到不可想象
查看>>
Android打包key密码丢失找回
查看>>
VC6.0调试技巧(一)(转)
查看>>
类库与框架,强类型与弱类型的闲聊
查看>>
webView添加头视图
查看>>
php match_model的简单使用
查看>>
在NT中直接访问物理内存
查看>>
Intel HEX 文件格式
查看>>
SIP服务器性能测试工具SIPp使用指导(转)
查看>>
回调没用,加上iframe提交表单
查看>>
(安卓)一般安卓开始界面 Loding 跳转 实例 ---亲测!
查看>>
Mysql 索引优化 - 1
查看>>
LeetCode(3) || Median of Two Sorted Arrays
查看>>
大话文本检测经典模型:EAST
查看>>
待整理
查看>>
一次动态sql查询订单数据的设计
查看>>
C# 类(10) 抽象类.
查看>>
Vue_(组件通讯)子组件向父组件传值
查看>>
jvm参数
查看>>