zoukankan      html  css  js  c++  java
  • 闭包函数,装饰器,写一个登录装饰器 (二层和三成装饰器)

    1.闭包函数

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

    当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数内部的其他变量,如果返回的这个函数在外部被执行了,就产生了闭包;
    闭包的作用及好处:
    闭包给访问外部函数定义的内部变量创造了条件,也将关于函数的一切封闭到了函数内部,减少了全局变量,这就是闭包的好处及真实意义,其实就是缓存了数据,变相的延长了作用域;

    什么是闭包函数:

    在一个内嵌套函数中,对在外部的函数变量进行引用,那么内嵌套函数就是闭包。

    定义在外部函数内但由内部函数引用的变量为自由变量,当作返回值。

    def f1():
         def f2():
             print('from f2')
    
         return f2
    
    f2 = f1()
    f2() #from f2
    

    闭包函数的用法:

    def wb_family():
    	father = "王健林"
    	def wbf_hobby():
    		print("先定一个小目标,赚它一个亿,这是爸爸{}说的".format(father))  # 条件1:内函数使用外函数的局部变量
    	return wbf_hobby  # 条件2:外函数返回了内函数
    
    func = wb_family()
    print(func)  # 这是打印函数 wb_family() 返回的 wbf_hobby函数名
    func() 
    

    1.1 两种为函数传参的方式

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

    def f1(url):
    
        print(url)
    
    f1(2)  
    f1(2)
    

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

    def f1(url):  # f1就叫做闭包函数
    
        def spider():
            print(url)
            
        return spider  # 函数对象
    
    taobao = f1('www.taobao.com')
    taobao()   # www.taobao.com
    tapbao()
    
    列二:
    def outer():
    	x = 0
    	def inner():
    		nonlocal x
    		x +=1
    		print(x)
    	return inner
    
    click_func = outer()
    click_func()  # inner()
    click_func()
    click_func()
    x = 100   # 在函数内部调用,起到封装作用,相对安全外部改变不了内部变量
    click_func()
    

    闭包函数:闭包函数把 闭包函数内部的变量 + 闭包函数内部的函数 这两者包裹在一起 然后通过返回值的形式返回出来

    闭包函数至少也得符合函数嵌套

    # def f1(url):  #1  #3 url:1
    #     def f2():  # 4 url:{int}1  #8 url={int}1
    #         print(url)  # 9 url:{int}1 
    #         pass  # 10
    #
    #     return f2    #5 url = {url}1  
    #
    #
    # res = f1(1)  #2  #6
    # res()  #1    #7  #11
    

    2. 装饰器

    装饰器:装饰(新增加了一个额外的功能) 器(工具) --》 函数

    装饰器本质就是一个给函数增加功能的函数。

    装饰器:给函数给函数 增加功能的 函数,增加功能时需要注意以下两点:

    装饰器注意点:

    1. 不改变原函数的源代码
    2. 不改变原函数的调用方式

    2.1装饰器

    1. 装饰器本身是函数,只不过它用来装饰 被装饰的函数
    2. 装饰器装饰函数 不改变被装饰函数源代码
    3. 装饰器装饰函数 不改变被装饰函数的调用方式

    列:

    # time_count装饰器:对被装饰函数计时
    def time_count(func):  # func才是真正的index
        """装饰器"""
    
        def wrapper(*args,**kwargs):  # (10, 20)  # *args和**kwargs接收了所有的参数
            start = time.time()
            res = func(*args,**kwargs)  # index()  # *(10,20)  # *args和**kwargs打散参数传给真正的index
            end = time.time()
            print(end - start)
    
            return res
    
        return wrapper
    
    index = time_count(index)  # index == wrapper
    res = index(10,20,320)  # wrapper()
    print(res)
    

    3.题:写一个登录装饰器 (二层和三成装饰器)

    # username_list = []
    #
    #
    # def index(x, y):
    #     print('index')
    #     print('x,y', x, y)
    #
    #     return 123
    #
    #
    # def login_deco(func):
    #     def wrapper(*args, **kwargs):
    #
    #         if username_list:
    #             print('已经登录,请勿重复登录')
    #             res = func(*args, **kwargs)
    #             return res
    #
    #         username_inp = input('请输入用户名:')
    #         pwd_inp = input('请输入密码:')
    #
    #         with open('user_info.txt', 'r', encoding='utf8') 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)
    #
    #                     res = func(*args, **kwargs)
    #                     return res
    #
    #             else:
    #                 print('登录失败')
    #
    #     return wrapper
    #
    #
    # index = login_deco(index)
    # index(10, 20)
    
    
    # index(10,20)
    
    
    # python装饰器语法糖(就是让代码更简洁)
    username_list = []
    
    
    def login_deco(func):
        def wrapper(*args, **kwargs):
    
            if username_list:
                print('已经登录,请勿重复登录')
                res = func(*args, **kwargs)
                return res
    
            username_inp = input('请输入用户名:')
            pwd_inp = input('请输入密码:')
    
            with open('user_info.txt', 'r', encoding='utf8') 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)
    
                        res = func(*args, **kwargs)
                        return res
    
                else:
                    print('登录失败')
    
        return wrapper
    

    二层装饰器:

    1. 用来装饰函数的,它本质是函数
    2. 不改变函数源代码
    3. 不改变函数调用方式
    # # 装饰器模板,如果装饰器真的不懂,记住模板
    # def deco(func):
    #     def wrapper(*args, **kwargs)
    

    三层装饰器:

    def sanceng()
    	def login_deco()
        	def wrapper(*args, **kwargs)
    

    4.余先了解 迭代器引用(就是一层层更新)

    类型:# 整型

    浮点型

    字符串

    列表

    元组

    字典

    集合

  • 相关阅读:
    快捷定位目录 z武器
    [UOJ317]【NOI2017】游戏 题解
    2-SAT 问题与解法小结
    link-cut-tree 简单介绍
    hihocoder #1456 : Rikka with Lattice(杜教筛)
    杜教筛小结
    BZOJ 2969: 矩形粉刷(期望)
    UVA10294 Arif in Dhaka (群论,Polya定理)
    BZOJ 1926: [Sdoi2010]粟粟的书架(主席树,二分答案)
    BZOJ 2683: 简单题(CDQ分治 + 树状数组)
  • 原文地址:https://www.cnblogs.com/WQ577098649/p/11574897.html
Copyright © 2011-2022 走看看