• 闭包函数及装饰器


    闭包函数及装饰器

    一、闭包函数

    1.1 函数传参的方式一

    def func(x):
        print(x)
    
    func(1)
    func(1)
    func(1)
    -------------------------------------------------------------
    1
    1
    1
    

    1.2 函数传参的方式二

    闭包函数,把变量和函数一起包起来,下次要用直接调用

    #这样传就不会每一次传参的时候都输入
    def outter(x):
        x = 1
    
        def inner():
            print(x)
        return inner
    
    f = outter(1)
    f()
    f()
    f()
    ---------------------------------------------------------
    1
    1
    1
    

    让我们再看一个利用闭包函数爬取网站的例子吧!

    import requests
    
    def func(url):
        def get_res():
            response = requests.get(url)
            print({url})
        return get_res
    
    baidu = func('https://www.baidu.com')
    
    baidu()
    baidu()
    -----------------------------------------------------------
    {'https://www.baidu.com'}
    {'https://www.baidu.com'}
    

    二、装饰器

    2.1 什么是装饰器

    装饰器:装饰的工具(函数),这个函数有装饰的作用

    装饰器本质就是一个函数A,装饰的对象也是一个函数B,用一个函数A去装饰一个函数B

    2.2 装饰器遵循的原则

    1. 不改变函数B的调用方式

    2. 不改变函数B的源代码

    def A():
        """装饰器"""
        pass
    
    def B():
        """被装饰的对象"""
        pass
    B()
    

    2.3 装饰器举例

    打印函数运行的时间

    # 2.3.1 改变了函数体代码,没改变调用方式(不是装饰器,没有遵循装饰器原则)
    import time
    
    def index():
        start = time.time()
        print('您好')
        time.sleep(1)
        end = time.time()
        print(end-start)
        
    index()
    ----------------------------------------------------------
    您好
    1.0013189315795898
    
    # 2.3.2 没改变调用方式,也没改变源码,但是不通用(不是装饰器,没有遵循装饰器原则)
    import time 
    def index():
        '''被装饰的函数'''
        print('hello')
    def index1():
        print('hello1')
        
        start = time.time()
        index()
        time.sleep(1)
        end = time.time()
        print(end-start)
        
        start = time.time()
        index1()
        time.sleep(1)
        end = time.time()
        print(end-start)
    -----------------------------------------------------------
    hello
    1.0003104209899902
    hello1
    1.000321388244629
    #每次调用的时候都得运行一遍,真的很麻烦
    
    # 2.3.3  真正的装饰器
    import time
    def index():
        print('您好啊!')
        time.sleep(1)
    
    def deco(func):    # func = 真正的index
        '''装饰器'''
        def f1():    #重新创建的index
            start = time.time()
            func()      #真正的index
            end = time.time()
            print(end-start)
        return f1
    
    index = deco(index)
    index()     #f1
    

    2.4 三层装饰器

    #利用装饰器写一个装饰器
    def auth(engine):
        def login(func):
            def inner(*args,**kwargs):
                #登录功能
                if engine =='file':
                    username = input('username:')
                    pwd = input('pwd:')
                    if username =='jiayi'and pwd =='123':
                        print('登录成功')
                        res = func(*args,**kwargs)  #shopping()
    
                        print('登录失败')
    
                elif engine =='db':
                    print('账号来自于数据库,非法请求')
    
            return inner
        return login
    @auth('db')
    def shopping():
        print('shopping')
    shopping()
    -------------------------------------------------------------------------
    账号来自于数据库,非法请求
    

    2.5 装饰器模板

    2.5.1 双层装饰器

    def outter(func):
        def wrapper(*args.**kwargs):  #wrapper是未来要运行的函数
            #加功能
            res = func(*args,**kwargs)  #func是被装饰的函数
            return res
        return wrapper
    @outter
    def shopping():
        print('shopping')
    

    2.5.2 三层装饰器

    # 三层装饰器:给双层装饰器加参数
    def sanceng (engine):
        def outter(func):
            def wrapper(*args,**kwargs):  # wrapper是未来要运行的函数
                #加功能
                print(engine)
                res = func(*args,**kwargs)  #func是被装饰的函数
                return  res
            return wrapper
        return outter
    
    @sanceng('db')
    def shopping():
        print('shopping')
    
  • 相关阅读:
    Web架构中的前端页面缓存
    Drools 使用Spring中的bean
    大型Java多用户商城系统设计开发的心得和困难
    正则表达式
    No ideal,no future
    关于sql 2005 assembly
    修改aspx输出的action地址 
    关于[META HTTPEQUIV="REFRESH" CONTENT=2]
    最简单的兼容firefox和ie的锚点方法
    【IIS】检索COM类工厂中CLSID为{0002450000000000C000000000000046}的组件时失败,错误: 80070005
  • 原文地址:https://www.cnblogs.com/yanjiayi098-001/p/11340438.html
Copyright © 2020-2023  润新知