前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >闭包函数和装饰器

闭包函数和装饰器

作者头像
GH
发布2022-05-10 15:58:05
3080
发布2022-05-10 15:58:05
举报

目录

闭包函数和装饰器

闭包函数

一、什么是闭包函数?

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

两种为函数传参的方式

为函数传参的方式一:使用参数的形式
代码语言: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
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-09-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 闭包函数和装饰器
    • 闭包函数
      • 一、什么是闭包函数?
      • 两种为函数传参的方式
      • 二、闭包函数的应用
    • 装饰器
      • 三层装饰器
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档