zoukankan      html  css  js  c++  java
  • 闭包函数和装饰器

    闭包函数和装饰器

    闭包函数

    一、什么是闭包函数?

    闭包:闭是封闭(函数内部嵌套函数),包是包含,闭包是指该内部函数对外部作用域而非全局作用域的变量的引用。

    两种为函数传参的方式

    为函数传参的方式一:使用参数的形式

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

    1

    为函数传参的方式二:包给函数

    def outter(x):
        x = 2
        def inner():
            print(x)
        return inner
    f = outter(1)
    f()
    

    2

    二、闭包函数的应用

    意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得该函数无论在何处调用,优先使用自己外层包裹的作用域。

    应用领域:延迟计算(原来是传参,现在是包起来)、爬虫领域。

    def f1(url):#f1闭包函数
        
        def spider():
            print(url)
            
        return spider#函数对象
    taobao = spider('https://www.taobao.com')
    taobao()
    

    装饰器

    所谓装饰器就是用一个函数给另一个函数加功能而且不动原函数的代码,不改变原函数的调用方式。

    import time
    
    def index():
        """被装饰的函数"""
        print('index')
        time.sleep(1)
    #为index增加计时功能
    def time_coount(func):
        """装饰器"""
        def f1():
            start = time.time()
            func()
            end = time.time()
            print(end-start)
        return f1
    index = time_coount(index)#这里第二个index是原来的index,但是第一个index已经不是原来的index,而是进过装饰之后的index
    index()
    
    1. 装饰器本身是函数,只不过用它来装饰被装饰的函数
    2. 装饰器装饰函数,不改变被装饰函数源代码
    3. 装饰器装饰函数,不改变被装饰函数的调用方式

    带返回值

    import time
    
    def index():
        """被装饰的函数"""
        print('index')
        time.sleep(1)
        return 10
    #为index增加计时功能
    def time_coount(func):
        """装饰器"""
        def f1():
            start = time.time()
            res = func()#如果原函数有返回值只需要将其赋给一个变量,然后将其在最内层返回
            end = time.time()
            print(end-start)
            return res
        return f1
    index = time_coount(index)
    print(index())
    

    index
    1.0000016689300537
    10

    加参数

    import time
    
    def index(x,y,z = 10):
        """被装饰的函数"""
        print('index')
        print(x,y,z)
        time.sleep(1)
        return 10
    #为index增加计时功能
    def time_coount(func):
        """装饰器"""
        def wrapper(*args,**kwargs):#不论被装饰函数有没有参数都可以这样写
            start = time.time()
            res = func(*args,**kwargs)
            end = time.time()
            print(end-start)
            return res
        return wrapper
    index = time_coount(index)
    index(10,20,30)
    

    index
    10 20 30
    1.0003015995025635

    为原函数加登录功能

    import time
    
    #为index增加计时功能
    username_list = []
    def time_coount(func):
        def wrapper(*args,**kwargs):
            if username_list:
                print('已经登录,请勿重复登录')
                start = time.time()
                res = func(*args, **kwargs)
                end = time.time()
                print(end - start)
                return res
            else:
                username_inp = input('请输入用户名:')
                pwd_inp = input('请输入密码:')
                with open('user_info.txt','r',encoding='utf-8') as fr:
                    for user_info in fr:
                        username,pwd = user_info.strip().split(':')
                        if username_inp == username and pwd_inp == pwd:
                            print('登陆成功')
                            username_list.append(username_inp)
                            start = time.time()
                            res = func(*args, **kwargs)
                            end = time.time()
                            print(end - start)
                            return res
                    else:
                        print('登陆失败')
    
        return wrapper
    @time_count
    def index(x,y,z = 10):
        """被装饰的函数"""
        print('index')
        print(x,y,z)
        time.sleep(1)
        return 10
    #index = time_coount(index)
    index(10,20,30)
    

    三层装饰器

    功能:给双层装饰器加参数

    在原来的要求上增加功能,需要判断用户动态的获取用户密码的方式,如果是file类型的,我们则让用户进行认证。

    import time
    
    #为index增加计时功能
    username_list = []
    def auth(engine):
        def time_count(func):
            def wrapper(*args,**kwargs):
                if engine == 'file':
                    if username_list:
                        print('已经登录,请勿重复登录')
                        start = time.time()
                        res = func(*args, **kwargs)
                        end = time.time()
                        print(end - start)
                        return res
                    else:
                        username_inp = input('请输入用户名:')
                        pwd_inp = input('请输入密码:')
                        with open('user_info.txt','r',encoding='utf-8') as fr:
                            for user_info in fr:
                                username,pwd = user_info.strip().split(':')
                                if username_inp == username and pwd_inp == pwd:
                                    print('登陆成功')
                                    username_list.append(username_inp)
                                    start = time.time()
                                    res = func(*args, **kwargs)
                                    end = time.time()
                                    print(end - start)
                                    return res
                            else:
                                print('登陆失败')
                else:
                    print('非法登录')
    
            return wrapper
        return time_count
    @auth('file')
    def index(x,y,z = 10):
        """被装饰的函数"""
        print('index')
        print(x,y,z)
        time.sleep(1)
        return 10
    #time_count = auth('file')
    #index = time_count(index)
    index(10,20,30)
    

    请输入用户名:xiaozhu
    请输入密码:12306
    登陆成功
    index
    10 20 30
    1.000612497329712

    装饰器语法糖

    在被装饰函数正上方,并且单独一行@装饰器名

    装饰器的模板

    def deco(func):
        def wrapper(*args,**kwargs):
            """加功能区域"""
            res = func(*args,**kwargs)
            return res
        return wrapper
    
  • 相关阅读:
    flex
    IOCP三:多个接收
    IOCP三:多个接收
    IOCP二:同时发送和接收
    IOCP二:同时发送和接收
    IOCP一:AcceptEx
    IOCP一:AcceptEx
    字符串和数字相互转换
    字符串和数字相互转换
    QThread应用详解
  • 原文地址:https://www.cnblogs.com/ghylpb/p/11574536.html
Copyright © 2011-2022 走看看