闭包函数和装饰器

2022-05-10 15:58:05 浏览数 (1)

目录

  • 闭包函数和装饰器
    • 闭包函数
      • 一、什么是闭包函数?
      • 两种为函数传参的方式
        • 为函数传参的方式一:使用参数的形式
        • 为函数传参的方式二:包给函数
      • 二、闭包函数的应用
    • 装饰器
        • 带返回值
        • 加参数
        • 为原函数加登录功能
      • 三层装饰器
        • 装饰器语法糖
        • 装饰器的模板

闭包函数和装饰器

闭包函数

一、什么是闭包函数?

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

两种为函数传参的方式

为函数传参的方式一:使用参数的形式
代码语言:javascript复制
def func(x):
    print(x)
    
    
func(1)

1

为函数传参的方式二:包给函数
代码语言:javascript复制
def outter(x):
    x = 2
    def inner():
        print(x)
    return inner
f = outter(1)
f()

2

二、闭包函数的应用

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

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

代码语言:javascript复制
def f1(url):#f1闭包函数
    
    def spider():
        print(url)
        
    return spider#函数对象
taobao = spider('https://www.taobao.com')
taobao()

装饰器

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

代码语言:javascript复制
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. 装饰器装饰函数,不改变被装饰函数的调用方式
带返回值
代码语言:javascript复制
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

加参数
代码语言:javascript复制
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

为原函数加登录功能
代码语言:javascript复制
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类型的,我们则让用户进行认证。

代码语言:javascript复制
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

装饰器语法糖

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

装饰器的模板
代码语言:javascript复制
def deco(func):
    def wrapper(*args,**kwargs):
        """加功能区域"""
        res = func(*args,**kwargs)
        return res
    return wrapper

0 人点赞