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

    闭包函数

    • 闭包指的是:函数内部函数对外部作用域而非全局作用域的引用。

    • 两种为函数传参的方式: 使用参数的形式; 包给函数

    def f1(x):
    	def f2():
    		print(x)
    	return f2
    	
    f = f1(5)  # f-->f2,x=5
    f()  # f()-->f2(),x=5  # 5
    f()  # 5
    
    
    f3 = f1(3)  # f-->f2,x=3
    f3()  # f()-->f2(),x=3  # 3
    f3()  # 3
    
    • 把内部定义的变量放到内部的函数中,让两者一起返回出去
    • 打破层级关系,把局部变量拿到全局使用,并且可以把外部的变量x封装到f2中,然后下次直接调用f2就可以了
    • 应用领域:延迟计算(原来我们是传参,现在是包起来),爬虫领域。

    装饰器

    1.什么是装饰器?

    ​ 装饰器指的是为被装饰器对象添加额外功能。因此定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数具有装饰的功能。

    需要注意的是:

    • 装饰器本身其实是可以任意可调用的对象
    • 被装饰的对象也可以是任意可调用的对象
    2.为什么要用装饰器?

    如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。

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

    1. 不修改被装饰对象的源代码
    2. 不修改被装饰对象的调用方式

    装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

    • 装饰器:改变功能的时候不改变原来的调用方式,并且改变原来函数的代码
    总结:
    • 调用装饰器并把sleep当作参数传入

    • 装饰器内部只有定义函数和一个返回函数,所以调用函数的时候不会执行wrapper函数,仅返回wrapper这个名字

    • 利用函数对象的概念将装饰器赋值给原函数名,相当于将wrapper这个名字赋值给原函数名

    • 原函数名+()执行的时候相当于调用装饰器内部的wrapper函数

    • wrapper函数的可变长形参会接收外层装饰器传入的所有参数并赋值给内层的函数,如果传入一个原函数的名字,则可以在最里层直接调用原函数

    • 最里层的函数是直接调用的而不是赋值,所以代码直接运行

    • wrapper函数内可以按需求增加功能,同时可以将最内层的函数(原函数)赋值给一个变量,在wrapper中返回这个值,可以让外层的函数使用

    
    def deco(func):
    	def wrapper(*args,**kwargs):  # 赋值后的time_sleep
    		res = func(*args,**kwargs)  # 真正的time_sleep
    		
    		return res
    	return wrapper
    
    @deco  # time_sleep(赋值后的) = deco(time_sleep(真正的))
    def time_sleep(name):
    	print(name)
    	return 123
    

    无参装饰器

    is_login_dict = {'username': None}
    
    
    def login_deco(func):
        
        def wrapper(*args, **kwargs):  # 赋值后的time_sleep
    
            if not is_login_dict['username']:
    
                username = input('请输入你的用户名》》》').strip()
    
                if username != 'fanping':
                    print('非法登录')
    
                    return
    
                is_login_dict['username'] = username
    
                res = func(*args, **kwargs)  # 真正的time_sleep
    
                return res
            else:
                res = func(*args, **kwargs)  # 真正的time_sleep
    
                return res         
    
        return wrapper
    
    
    @login_deco
    def shopping():
        print('from shopping')
    
    
    @login_deco
    def withdraw():
        print('from withdraw')
    

    有参装饰器

    is_login_dict = {'username': None}
    
    def auth(origin):
        
        def login_deco(func):
    
            def wrapper(*args, **kwargs):  # 赋值后的time_sleep
    
                if origin == 'file':
    
                    if not is_login_dict['username']:
    
                        username = input('请输入你的用户名》》》').strip()
    
                        if username != 'fanping':
                            print('非法登录')
    
                            return
    
                        is_login_dict['username'] = username
    
                        res = func(*args, **kwargs)  # 真正的time_sleep
    
                        return res
                    else:
                        res = func(*args, **kwargs)  # 真正的time_sleep
    
                        return res
    
                elif origin == 'mongodb':
                    print('非法登录')
                    
                else:
                    print('dsb')
    
    
            return wrapper
        
        return login_deco
    
    
    # f = origin('file')  # login_deco
    # shopping = f(shopping)
    # shopping()
    
    
    @auth('file')
    def shopping():
        print('from shopping')
    
    
    @auth('mongodb')
    def withdraw():
        print('from withdraw')
    
  • 相关阅读:
    OSGi for C/C++
    Tizen NPPlugin开发
    Trove4j
    [Tizen]某些目录下存放的东西
    OpenMobile's Application Compatibility Layer (ACL)
    params
    页面无法访问
    websevice 服务前台和后台
    SQL 创建存储过程
    UpdatePanel
  • 原文地址:https://www.cnblogs.com/gongjingyun123--/p/10957086.html
Copyright © 2011-2022 走看看