python装饰器函数执行后日志_你必须学写 Python 装饰器的五个理由-程序员宅基地

技术标签: python装饰器函数执行后日志  

原标题:你必须学写 Python 装饰器的五个理由

来源:Python程序员

ID:pythonbuluo

你必须学写Python装饰器的五个理由

----装饰器能对你所写的代码产生极大的正面作用

作者:Aaron Maxwell,2016年5月5日

Python装饰器是很容易使用的。任何一个会写Python函数的人都能够学会使用装饰器,比如下面这个:

@somedecorator

defsome_function():

print("Check it out, I"m using decorators!")

但是,写出一个装饰器是一个完全不一样的技能。而且这也不是,你不得不理解下面这些:

闭包

如何将函数作为"第一类"参数来使用

变量参数

参数解包

甚至是Python是如何装载源码的一些细节

所有这些都需要花很多时间去理解和掌握。而且当你已经有这么一堆事情要学的时候,这些值得你花时间吗?

对我来说,这个问题的答案已然是上千次的“肯定,是的,我会学习!”

写装饰器的最重要的好处是什么呢?在你每天的开发中,装饰器让你做什么做起来是很容易并且很强大的呢?

分析、日志以及指导

尤其是在大型软件中,我们通常需要专门来测试到底发生了什么,以及记录那些能量化不同行为的指标。通过在装饰器内部的函数或者方法里面封装这些重要的事件,这个装饰器能通俗易懂且容易地处理刚才这些所讲的需求。比如:

frommyapp.log importlogger

deflog_order_event(func):

defwrapper(*args, **kwargs):

logger.info("Ordering: %s", func.__name__)

order = func(*args, **kwargs)

logger.debug("Order result: %s", order.result)

returnorder

returnwrapper

@log_order_event

deforder_pizza(*toppings):

# let"s get some pizza!

同样的方式可以被用来计数或者其他指标。

验证与运行检查

Python的类型系统是相当类型化了的,但是也是很动态的。对于它的这些所有的好处,也意味着某一些bugs能够悄悄产生,而这些bugs能够在编译的时候被更类型化的语言(比如Java)所捕获。即使更长远看,你可能需要强化更复杂的,在数据进出的时候能个性化检查。装饰器能让你易于处理所有这些,并能一次性地应用它到很多函数上。

假设:你有一堆函数,每个函数都返回一个字典,这个字典包含一个称作“summary”的字段。这个字段的值不能超过80个字符长度;如果违反了,就是不对的。这里给出一个装饰器,当条件不满足的时候它能够抛出一个值错误(ValueError),如下:

defvalidate_summary(func):

defwrapper(*args, **kwargs):

data = func(*args, **kwargs)

iflen(data["summary"]) > 80:

raiseValueError("Summary too long")

returndata

returnwrapper

@validate_summary

deffetch_customer_data():

# ...

@validate_summary

defquery_orders(criteria):

# ...

@validate_summary

defcreate_invoice(params):

# ...

创建框架

一旦你掌握了装饰器的编程,你将能够受益于使用装饰器的简单语法,而这让你增加语意给你的代码以便容易使用它。这就是下一个能够扩展Python自身语法的最好的工具。

实际中,很多流行的开源框架都在使用装饰器。网页应用框架Flask就使用了装饰器将URLs的路由交给那些处理HTTPS请求的函数。

# For a RESTful todo-list API.

@app.route("/tasks/", methods=["GET"])

defget_all_tasks():

tasks = app.store.get_all_tasks()

returnmake_response(json.dumps(tasks), 200)

@app.route("/tasks/", methods=["POST"])

defcreate_task():

payload = request.get_json(force=True)

task_id = app.store.create_task(

summary = payload["summary"],

deion = payload["deion"],

)

task_info = {"id": task_id}

returnmake_response(json.dumps(task_info), 201)

@app.route("/tasks//")

deftask_details(task_id):

task_info = app.store.task_details(task_id)

iftask_info is None:

returnmake_response("", 404)

returnjson.dumps(task_info)

在这里,你有一个被叫做app的全局的对象,它有一个被称作route(路由)的方法并接受特定参数。这个路由方法返回一个被应用到处理函数的装饰器。在这个“面罩”下发生了一些很错综复杂的的事情,但是从Flask的使用者角度看,所有这些复杂性是完全被隐藏起来的了。

以这样的方式使用装饰器在stock Python中也有体现。举个例子,完全使用对象系统是有赖于@classmethod和@property装饰器的:

classWeatherSimulation:

def__init__(self, **params):

self.params = params

@classmethod

deffor_winter(cls, **other_params):

params = {"month": "Jan", "temp": "0"}

params.update(other_params)

returncls(**params)

@property

defprogress(self):

returnself.completed_iterations() / self.total_iterations()

这个类有3个不同的定义声明。但是,他们的语意是各不相同的。

1:constructor是一个正常方法

2:for_winter是一个类方法且提供一种类似于“车间”的东西

3:progess是只读、动态属性

对于日常来说,@classmethod和@property两个装饰器如此简单以致可以很容易扩展Python的对象语意

复用那些不可能复用的代码

Python提供给你一些很强大的工具用以封装代码为一个易用的形式,并带有充分的函数表示语法,支持函数式编程以及全面的对象系统。但是,装饰器也有它所不能捕获的某些形式的代码复用。

比如使用一个不可靠的API。你给那些通过HTTP对话的JSON发出一些请求的时候,API可以99.9%的时候工作正常。但是,有一小部分请求将使得服务器返回一个内部错误,然后你需要重试这些请求。在这个情况下,你将写一个重试逻辑,比如:

resp = None

whileTrue:

resp = make_api_call()

ifresp.status_code == 500andtries < MAX_TRIES:

tries += 1

continue

break

process_response(resp)

现在,假设你有十多个类似于make_api_call的函数,并且他们被所有代码调用。那么你是想要每次调用它们的时候写一个while循环呢?还是每次增加一个API调用函数的时候都把这段代码再写一遍?无论哪种选择都会产生大量的重复代码,除非你用装饰器。用了装饰器事情就简单了。

# 加了装饰器的函数会返回一个Response对象,

# 这个对象有个一二status_code的属性,

# 200表示成功;500表示服务器错误。

defretry(func):

defretried_func(*args, **kwargs):

MAX_TRIES = 3

tries = 0

whileTrue:

resp = func(*args, **kwargs)

ifresp.status_code == 500andtries < MAX_TRIES:

tries += 1

continue

break

returnresp

returnretried_func

上述例子可以让你方便使用装饰器@retry

@retry

defmake_api_call():

# ....

提升你的职业生涯

编写装饰器在一开始并不容易。它虽然不像火箭科学但是也需要你花很多努力去学习,去排除一些细微差异。很多开发者也从来不会通过这些麻烦而学习掌握装饰器编写。但是学习装饰器的确会给你优势。当你是你的团队里面学习如何写好装饰器的那个人的时候,并且你写的装饰器能解决一些实际问题的时候,其他开发者将会使用你的装饰器。因为,一旦这些装饰器编写的困难的部分被完成了,装饰器就会很容易使用。这就对你所写的代码产生极大的正面作用。这也会让你成为一个重要角色。

不论你如何编写装饰器,你会对下面你所要做的事情而感到兴奋,比如你即将能使用装饰器来做一些事情,以及装饰器是如何能永远改变你写Python代码的方式。

英文原文:https://www.oreilly.com/ideas/5-reasons-you-need-to-learn-to-write-python-decorators

译者:gvicky 返回搜狐,查看更多

责任编辑:

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_40001372/article/details/110028865

智能推荐

canal 全量/增量数据同步说明_canal 全量同步数据-程序员宅基地

文章浏览阅读7.4k次,点赞3次,收藏8次。一、日志文件完整1、全量数据同步1、修改\canal.deployer-1.1.5\conf\example下的instance.properties通过以下三个配置实现canal全量数据同步# mysql日志文件canal.instance.master.journal.name=mysql-bin.000001# 获取日志的起始位置canal.instance.master.position=0# 获取日志的起始时间戳canal.instance.master.timestamp=16_canal 全量同步数据

法语电话面试程序员面试问题和汇总-程序员宅基地

文章浏览阅读885次,点赞24次,收藏18次。法语电话面试程序员面试问题和汇总

全金属vivaldi天线设计----学习笔记_(1)vivaldi天线(ava)设计-程序员宅基地

文章浏览阅读1.1k次,点赞3次,收藏19次。全金属 Vivaldi 天线单元为宽频带单元,其在自由空间中孤立单元的特性与构成阵列的阵元的特性是不同的。_(1)vivaldi天线(ava)设计

springboot-开机自启功能实现-CommandLineRunner和ApplicationRunner_springboot 开机自启动-程序员宅基地

文章浏览阅读212次。区别:1.两个接口的实现方法一样,参数不一样,其他没什么区别。两个参数都可以接收java命令设置的参数及值2.ApplicationRunner接口的实现方法比CommandLineRunner接口的实现方法前执行(也可通过设置@Order决定谁先执行)作用:满足springBoot框架需要预加载数据需求,执行操作的时间是在容器启动末尾时间执行操作。_springboot 开机自启动

vsCode 快捷键-程序员宅基地

文章浏览阅读45次。记住常用的快捷键,对开发来说,简直是行云流水,心里无比顺畅。按 Press功能 FunctionCtrl + Shift + P,F1显示命令面板 Show Command PaletteCtrl + P快速打开 Quick OpenCtrl + Shift + N新窗口/实例 New window/instanceCtr...

Devin:全球首个AI程序员!自主学习,写代码,查bug!_devin ai-程序员宅基地

文章浏览阅读2k次,点赞30次,收藏22次。Devin:全球首个AI程序员!自主学习,写代码,查bug!_devin ai

随便推点

手机python编程软件哪个好,手机python编程软件app-程序员宅基地

文章浏览阅读885次,点赞16次,收藏20次。正确的用法,应该就是学编程的时候,用来练习练习,倒是一个不错的好选择,或者自己有些小项目,拿来码码代码什么的。由于内置了SL4A,可以很方便的调用安卓操作系统的一些API做些有趣的事情,比如可以通过SL4A获取手机地理位置,打开蓝牙,发送手机短信,打开手机摄像头等等。Qpython是一个Python引擎,只能运行在安卓系统上,内置了一个Python编辑器,可以直接在手机上写Python代码,支持缩进,语法高亮等特性。这是编程IDE的标配,可以执行一些代码片段,不过写手机上输入代码还是挺麻烦的。

Day01:Web应用&架构搭建&站库分离&路由访问&配置受限&DNS解析_架构搭建-站库分离-路由访问-配置受限-dns解析-程序员宅基地

文章浏览阅读891次,点赞14次,收藏17次。小迪安全-Day01:Web应用&架构搭建&站库分离&路由访问&配置受限&DNS解析_架构搭建-站库分离-路由访问-配置受限-dns解析

计算机毕业设计(附源码)python中小学家校通系统_家校一体化教育系统的开发python-程序员宅基地

文章浏览阅读235次。考试成绩管理,在考试成绩管理页面中可以对索引、家长账号、家长姓名、学号、学生姓名、班级、学年、学期、科目、考试成绩、等级、教师评语、教师工号、教师姓名等信息进行详情,修改或删除等详细操作,如图5-9所示。家长管理,在家长管理页面中可以对索引、家长账号、家长姓名、性别、头像、学号、学生姓名、班级、年龄、关系、家长手机、家长邮箱等信息进行详情、修改或删除等详细操作,如图5-5所示。个人中心,在个人中心页面通过填写家长账号、家长姓名、性别、头像、学号、学生姓名、班级、年龄、关系、家长手机、家长邮箱等信息进行。_家校一体化教育系统的开发python

修改Matlab的背景颜色_matlab背景颜色-程序员宅基地

文章浏览阅读1.9k次。然后,使用"set"函数和"gcf"参数来设置当前图形窗口的属性。总结一下,通过使用Matlab的"figure"函数和"Color"属性,我们可以轻松修改Matlab的背景颜色。本文将详细介绍如何使用Matlab代码修改背景颜色。需要注意的是,上述代码中的"set"函数将背景颜色设置为当前图形窗口的属性。如果你想要修改特定的图形对象或图形句柄的背景颜色,可以将"set"函数中的"gcf"替换为相应的图形对象或图形句柄。要修改Matlab的背景颜色,我们可以使用"figure"函数和"Color"属性。_matlab背景颜色

Ubuntu14.04和16.04官方默认更新源sources.list和第三方源推荐(干货!)_ubuntu16.04 源 source.list-程序员宅基地

文章浏览阅读6.9k次,点赞2次,收藏14次。写在前面:笔者由于还在学校学习,学校没有开发给Linux用的上网客户端,所以只能用在windows系统中通过安装虚拟机运行linux比较方便,但没有外网,只有学校的教育网,所以我需要将ubuntu的默认源修改为教育网中的资源才可以完美运行ubuntu,当然这个教程也适用于修改为非教育源。 第一步,备份官方的默认源  避免自己手贱操作失误,重装系统太费时间cp /etc/apt/sources.li..._ubuntu16.04 源 source.list

devops资料大全-程序员宅基地

文章浏览阅读652次。备份备份软件Amanda -客户端-服务器模型备份工具Bacula - 另一个客户端-服务器模型备份工具Backupninja -轻量级,可扩展的元数据备份系统Backuppc -客户端-服务器模型备份工具和文件共享方案。Burp -网络备份和还原程序Duplicity -使用rsync算法加密的带宽-效率备份Lsyncd -监控一个本地目录树的变..._devops 大全