【Pyhont笔记】装饰器总结

Python函数进阶:闭包、装饰器、生成器、协程 目录 (1)闭包 (2)装饰器 (3)生成器 (4)协程 (1)闭包 闭包(closure)是很多现代编程语言都有的特点,像C++、Java、JavaScript等都实现或部分实现了闭包功能,很多高级应用都会依靠闭包实现。 一般专业文献上对闭包的定义都比较拗口,比如:“将组成函数的语句和这些语句的执行环境打包在一起时,得到的对象称为闭包。” 其实,简单来说,你可以将闭包看成是一个轻载的类,... 阅读详情

知识点:python中函数也是对象,可以传递和当做参数的。

装饰器可看成是一个复杂语法的缩写:

@a

def b

       ...

等价于

b=a(b)

 

1.最基本的装饰器:参数为函数,返回函数的函数,可作为修饰器

def decorator(in_func):#函数做参数
    def out_func(a,b,c):
        print("输出点啥")
        return in_func(a,b,c)
    return out_func#返回函数,参数需要与被装饰函数(use_func)参数一致,或者用*args,**kwargs
    
#使用

@decorator
def use_func(a,b,c):
    ...

#等价于
use_func=decorator(use_func)

问题1:名称信息丢失

print(use_func.__name__)#被装饰函数名称
# Output: wrapTheFunction

解决方法:

from functools import wraps
 
def decorator(in_func):
    @wraps(in_func)
    ...
    return out_func#返回函数


print(use_func.__name__)#被装饰函数名称
# Output: use_func

注意:@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

 

问题2:use_func的参数如何获得的

use_func的参数是如何获得的:

我们可以在定义 out_func 函数的时候指定参数:
def out_func(a,b,c):
        logging.warn("%s is running" % in_func.__name__)
        return in_func(a,b,c)
return out_func

这样 use_func 函数定义的参数就可以定义在 out_func函数中。use_func如果有很多个参数。当装饰器不知道 use_func 到底有多少个参数时,我们可以用 *args 来代替:

def out_func(*args):
        logging.warn("%s is running" % in_func.__name__)
        return in_func(*args)
return out_func

对于use_func 函数还定义了的关键字参数比如:

def use_func(name, age=None, height=None):
    ...

这时,可以把 out_func 函数指定关键字函数:

def out_func(*args, **kwargs):
        # args是一个数组,kwargs一个字典
        logging.warn("%s is running" % in_func.__name__)
        return in_func(*args, **kwargs)
return out_func

 

2.带参数的装饰器:

例1:

装饰器还有更大的灵活性,例如带参数的装饰器,在上面的装饰器调用中,该装饰器接收唯一的参数就是执行业务的函数 use_func 。装饰器的语法允许我们在调用时,提供其它参数,比如@decorator(a)。这样,就为装饰器的编写和使用提供了更大的灵活性。比如,我们可以在装饰器中指定日志的等级,因为不同业务函数可能需要的日志级别是不一样的。

def use_logging(level):
    def decorator(in_func):
        def out_func(*args, **kwargs):
            if level == "warn":
                logging.warn("%s is running" % in_func.__name__)
            elif level == "info":
                logging.info("%s is running" % in_func.__name__)
            return in_func(*args)
        return out_func

    return decorator

@use_logging(level="warn")
def foo(name='foo'):
    print("i am %s" % name)

foo()

上面的 use_logging 是允许带参数的装饰器。它实际上是对原有装饰器的一个函数封装,并返回一个装饰器。我们可以将它理解为一个含有参数的闭包。当我 们使用@use_logging(level="warn")调用的时候,Python 能够发现这一层的封装,并把参数传递到装饰器的环境中。

@use_logging(level="warn")等价于@decorator

例2:

from functools import wraps
 
def logit(logfile='out.log'):
    def logging_decorator(func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            log_string = func.__name__ + " was called"
            print(log_string)
            # 打开logfile,并写入内容
            with open(logfile, 'a') as opened_file:
                # 现在将日志打到指定的logfile
                opened_file.write(log_string + '\n')
            return func(*args, **kwargs)
        return wrapped_function
    return logging_decorator
 
@logit()
def myfunc1():
    pass
 
myfunc1()
# Output: myfunc1 was called
# 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串
 
@logit(logfile='func2.log')
def myfunc2():
    pass
 
myfunc2()
# Output: myfunc2 was called
# 现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串

3.装饰器类:

装饰器不仅可以是函数,还可以是类,相比函数装饰器,类装饰器具有灵活度大、高内聚、封装性等优点。使用类装饰器主要依靠类的__call__方法,当使用 @ 形式将装饰器附加到函数上时,就会调用此方法。

from functools import wraps
 
class logit(object):
    def __init__(self, logfile='out.log'):
        self.logfile = logfile
 
    def __call__(self, func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            log_string = func.__name__ + " was called"
            print(log_string)
            # 打开logfile并写入
            with open(self.logfile, 'a') as opened_file:
                # 现在将日志打到指定的文件
                opened_file.write(log_string + '\n')
            # 现在,发送一个通知
            self.notify()
            return func(*args, **kwargs)
        return wrapped_function
 
    def notify(self):
        # logit只打日志,不做别的
        pass

这个实现有一个附加优势,在于比嵌套函数的方式更加整洁,而且包裹一个函数还是使用跟以前一样的语法:

@logit()
def myfunc1():
    pass

现在,我们给 logit 创建子类,来添加 email 的功能(虽然 email 这个话题不会在这里展开)。

class email_logit(logit):
    '''
    一个logit的实现版本,可以在函数调用时发送email给管理员
    '''
    def __init__(self, email='admin@myproject.com', *args, **kwargs):
        self.email = email
        super(email_logit, self).__init__(*args, **kwargs)
 
    def notify(self):
        # 发送一封email到self.email
        # 这里就不做实现了
        pass

从现在起,@email_logit 将会和 @logit 产生同样的效果,但是在打日志的基础上,还会多发送一封邮件给管理员。

参考自:

1:https://www.runoob.com/w3cnote/python-func-decorators.html\

2:https://foofish.net/python-decorator.html

Python_day07--装饰器(一般用作时间装饰、密码验证等) 一、高阶函数的返回值为函数--初识装饰器通过上一节的学习我们了解了,当我们定义一个函数的def时,它的return值一般为一个数值或是一个运算表达式,但是在我们的学习过程中会发现一些问题,当我们已经写好的一段代码并且逻辑非常绕,但是现在需要我们对他做一些改动时你会发现完全无从下手,只要改变之前的代码就会报错,并且是接踵而至麻烦不断。所以我们这里就要引进一个更方便更快捷---------装饰器1、什... 阅读详情

相关推荐

linux 内核vxlan收发包流程

1.vxlan口收包处理流程 前面几章详细介绍了vxlan接口的使用,而且已经知道vxlan是 MAC IN UDP中的封装,因此,在解封装之前,一切按照原有流程走,在此复习一下内核收发包流程(驱动层的数据处理这次不再解析,直接从__netif_receive_skb_core开始) #物理网卡处理中断,触发softirq i40e_intr └─napi_schedule_irqoff #i40e softirq把包放到per cpu backlog,触发softirq i40e_napi_p

魏言华的博客 3826

Python -- 函数

Python -- 函数

weixin_43889788的博客 1952

倍福 MODBUS TCP/IP通信

(*默认字符串80字节,此处声明为255字节,可以一次性传42个UINT数据.5位整数加一个空格,即每个数据6字节*)(*---------------------------------------- 以下为用户程序 ----------------------------------------*)(*读回并换算后的值*)(*准备写到PLC的值*)(*用于比较两次读回的值相差多少,以估计通讯的速度, Act_CalcDiff*)(*用于切换读和写,Act_Protocal*)

qq_33280096的博客 1367

python 使用 with open() as 读写文件

读文件: 要以读文件的模式打开一个文件对象,使用Python内置的open()函数,传入文件名和标示符: >>> f = open('E:\python\python\test.txt', 'r') 标示符'r'表示读,这样,我们就成功地打开了一个文件。 如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在: ...

xrinosvip的博客 50万+

从想法到零件:手把手拆解一个汽车功能如何从PRD写到SSTS和CTS

本文详细拆解了汽车电子需求从市场文档(MRD)到零部件技术规范(CTS)的完整流程,以雨天自动关窗功能为例,展示了PRD、SSTS和CTS的编写要点与交互设计。文章重点解析了系统分解的艺术和零部件落地的精确参数要求,为汽车电子工程师提供了从概念到实现的全流程实践指南。

weixin_30300225的博客 481

CELF(Cost-Effective Lazy Forward selection)具有成本效益的惰性前向选择算法

CELF(Cost-Effective Lazy Forward selection)算法解析      引言:在社交网络影响力最大化问题的求解过程中,我们往往需要去选择一些目标种子结点作为信息初始传播的源头。贪婪算法在传播效果上的解决可以达到影响的最大化,但是在时间复杂度上面显得确十分糟糕。为此CELF算法应势而生,CELF算法利用了函数次模性的特点,在第一轮选择种子结点时,计算网络中所有节点的边际收益,但将在之后的过程中,不再做网络节点边际收益的重复计算,这相对于传统的贪婪算法,将在时间上得到非常明显的

hahaxq的博客 2477

python笔记——文件读写操作过程(open与with open的区别)

文件的读写通常包含以下步骤: 文件的打开:open() open或with open会返回文件对象,必须用read或readlines之后才能打印 在此我会介绍with open 与open之间的区别。提前剧透with open优于open 文件的读入:read() 文件的写入:write() 文件的关闭:close() 另外介绍两个模块的内容: 文件的定位 文件的属性 一、文件的打开:o...

阿斯达克 3364

MATLAB - 利用非线性模型预测控制(Nonlinear MPC)来控制四旋翼飞行器

本示例展示了如何利用非线性模型预测控制(MPC)为四旋翼飞行器设计一个跟踪轨迹的控制器。

机器人控制与仿真应用 4432

python高级编程-装饰器学习笔记

python装饰器 装饰器(Decorators)是Python的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短,也更Pythonic(Python范儿)。大多数初学者不知道在哪儿使用它们,所以我将要分享下,哪些区域里装饰器可以让你的代码更简洁。 首先,让我们讨论下如何写你自己的装饰器。 1、一切皆对象 我们先来理解下P

sisiair的博客 720

企业数字化转型解决方案架构设计:一个五维全景视角

本文系统探讨了企业数字化转型的架构设计框架,提出五维协同模型:企业架构作为战略罗盘,业务架构聚焦价值创造,应用架构实现能力载体,数据架构提供智能燃料,技术架构奠定基础支撑。文章深入分析了各架构域的核心要素、设计原则及相互关系,并指出数字化转型需通过渐进路径,结合战略引领、技术赋能和组织变革,构建有机统一的架构体系。该框架为企业应对数字化复杂性提供了系统性方法论,强调从整体视角实现技术与业务的深度融合。

金牌架构师 1256

华为用自研的MetaERP替换全球顶级的SAP ERP系统,其难度与风险远超一次普通的技术升级,它是一场战略级的、涉及业务筋骨的系统性工程

华为成功用自研MetaERP替换SAP系统,这是一项极具挑战的战略工程。面临四大难度:业务复杂度高(170多国业务)、数据迁移量大(20年历史数据)、技术集成复杂(重构生态系统)、人员适应周期长。同时伴随四大风险:业务中断、数据失真、成本超支、供应链协同问题。华为成功的关键在于:生存压力驱动的战略决心、强大的软件研发能力、以自身业务为试验场、分步实施策略。这一案例证明中国企业能攻克高端软件壁垒,但对大多数企业而言,核心系统替换需谨慎评估风险,建议采用渐进式替代策略。

金牌架构师 535

第六课--python的装饰器

装饰器是对闭包函数的操作。也是python中独有的。创建了一个装饰器之后,只需在其他方法或函数的顶部使用@装饰器名称就可以了。 看案例 from datetime import datetime def run_time(fun): def new_fun(): s_time = datetime.now() fun() e_time ...

阅读之后,对你有帮助,那就点个赞再走吧 356

【CloudCompare教程】017:点云快速全局配准

点云数据的配准分为基于特征(特征点、特征线)的拼接和无特征拼接。特征点匹配的方法和全局ICP的方法。特征点的方法通过全局特征匹配达到全局配准,全局ICP的方法通过对变量空间进行搜索的方法达到全局最优解。

智慧空间实验室 3929

Python:retrying重试装饰器的使用

文档:https://pypi.org/project/retrying/ 依赖 pip install retrying 示例 # -*- coding: utf-8 -*- from retrying import retry # 最多执行5次 @retry(stop_max_attempt_number=5) def foo(): print("foo") raise Exception("Exception") if __name__ == '__main__':

彭世瑜的博客 1636

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Python中的类方法和静态方法

作者:黎智煊 ,叩丁狼高级讲师。本文为原创文章,转载请注明出处。     类方法 是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以'cls'作为第一个参数的名字,就最好用'cls'了),能够通过实例对象和类对象去访问。 class Pe...

wolfcode_cn的博客 1992

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

python顺序执行_python执行顺序

广告关闭腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元!修改规则执行顺序默认接口请求频率限制:20次秒。 推荐使用 api explorer 点击调试 api explorer 提供了在线调用、签名验证、sdk代码生成和快速检索接口等能力。 您可查看每次调用的请求内容和返回结果以及自动生成 sdk 调用示例。 2. 输入参数以下请求参数列...

weixin_39869733的博客 1550

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Python装饰器(Decorator)完全指南-基础篇

Python中decorator事实上即是一个接受函数作为输入变量并返回另一个函数对象的函数。

正西风落叶下长安 1109

python中装饰器详解

装饰器 我们知道,在python中,我们可以像使用变量一样使用函,这主要依赖于以下几点: 函数可以被赋值给其他变量 函数可以被删除 可以在函数里面再定义函数,函数嵌套。 函数可以作为参数传递给另外一个函数 函数可以作为另一个函数的返回值 对一个简单的函数进行装饰 为了更好的理解装饰器,我们先从一个简单的例子开始,假设有下面这个函数: def hello(): return...

AFeng521web 7939

pyhon装饰器

pyhon的装饰器有无参数和有参数之分,有参数只是在无参数的基础上再包一层,写了一个有参数的作为例子 def decorator_for_args(*args_for_decorator): def outer(function): def inner(*args, **kwargs): for i in args_for_decorator:

epugv的专栏 1268

【Python】conda镜像配置,.condarc文件详解,channel镜像

安装miniconda即可,Miniconda 安装包可以到下载。.condarc是conda 应用程序的配置文件,在用户家目录(windows:C:\users\username\),用于管理镜像源。

Code_LT的博客 9万+

Python-可扩展性方案,register使用

文档 官方: 教程: 基础:https://applenob.github.io/python/register/ 简单示例:https://www.jianshu.com/p/8b2c915dc39f 深度学习种使用注册器:https://zhuanlan.zhihu.com/p/350787676 笔记 #使用注册器 if __name__ == "__main__": register_obj = RegisterMachine("register") # decorate metho

Code_LT的博客 3885

【Pyhont笔记】__new__和__init__

一、先理解cls和self 此部分原文:https://blog.youkuaiyun.com/daijiguo/article/details/78499422 1、self表示一个具体的实例本身。如果用了staticmethod,那么就可以无视这个self,将这个方法当成一个普通的函数使用。 2、cls表示这个类本身。 >>> class A(object): def foo1(self): print "Hello",self @

Code_LT的博客 3679

【Pyhont笔记】小知识点

1.文档字符串对于类,函数/方法,以及模块来说是唯一的,也就是说doc属性是不能从父类中继承来的。

Code_LT的博客 3632

把idea或pycharm的虚拟环境用于jupyterlab

通常,我们如果在idea或pycharm中创建了虚拟环境,都会下载很多各工程需要的库,不希望在jupyterlab中再去下载一遍。这样的背景下,我们只需要把idea或pycharm的虚拟环境,安装到jupyterlab的kenel中就可以了。其中"xxx"表示jupyterlab想显示的虚拟环境的名字,这样就可以在JupyterLab中使用这个虚拟环境了。打开idea或pycharm,点底部的terminal,进入到这个虚拟环境中,然后运行命令。重新打开jupyterlab,即可选用你的"xxx"核。

Code_LT的博客 1726

【Python】基础学习&技能提升&代码样例1:简单句式

可迭代对象的例子包括所有序列类型(如 list, str 和 tuple 等)以及某些非序列类型如 dict, 文件对象 以及任何定义了。如果传入了额外的 iterables 参数,则 function 必须接受相同个数的参数并被用于到从所有可迭代对象中并行获取的项。map() 和 starmap() 之间的区别类似于 function(a,b) 和 function(*c) 之间的差异。返回一个将 function 应用于 iterable 的每一项,并产生其结果的迭代器。时,它会返回该对象的迭代器。

Code_LT的博客 1474
上一篇: 【Pyhont笔记】__new__和__init__
下一篇: 【python笔记】hashable -- 可哈希
Code_LT
博客等级 码龄10年 307粉丝 182原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值