Python装饰器-给你的咖啡加点料
今天你的咖啡加糖了吗? 让我们通过一个简单的例子来引出装饰器的概念及用法。在引出装饰器之前,我们先来了解一下函数的概念。 一、函数回顾 1、在python中函数是一等公民,函数也是对象。我们可以把函数赋予变量。
def make_cofe(type):
print('获得一杯 : {}'.format(type))
get_cofe = make_cofe
get_cofe('咖啡')
####输出#####
获得一杯 : 咖啡
这个例子中,我们把函数make_cofe 赋予了变量 get_cofe,这样之后你调用 get_cofe,就相当于是调用函数 make_cofe()。 2、把函数当作参数,传入另一个函数中。
def make_cofe(type):
print('获得一杯 : {}'.format(type))
def shop(func,type):
func(type)
shop(make_cofe,'咖啡')
####输出####
获得一杯 : 咖啡
这个例子,我们把make_cofe以参数的形式传入shop中,然后调用它。 3、函数是可以嵌套的。
def shop(type):
def make_cofe(type):
print('获得一杯 : {}'.format(type))
make_cofe(type)
shop('咖啡')
#####输出####
获得一杯 : 咖啡
这段代码中,我们在函数shop内部定义了函数make_cofe 4、函数的返回值也可以是函数对象(闭包)。
def shop():
def make_cofe(type):
print('获得一杯 : {}'.format(type))
return make_cofe
get_cofe=shop()
get_cofe("咖啡")
####输出#####
获得一杯 : 咖啡
这里,函数 shop() 的返回值是函数对象 make_cofe 本身,之后,我们将其赋予变量 get_cofe,再调用 get_cofe("咖啡")。 二、装饰器 下面我们正式开始装饰器的学习。 我们先想一个问题。如果我们去咖啡店要一杯咖啡,我们应该如何实现。你也许会这么写。
def cofe():
print('咖啡', end='')
cofe()
####输出####
咖啡
那我们现在想来一杯加糖咖啡,我们该如何写呢?你也许会这么想,那还不简单,直接在cofe()函数里改不就好了。
def cofe():
print('加糖咖啡', end='')
cofe()
####输出####
加糖咖啡
那么问题来了,如果我们现在不想喝加糖咖啡了,该怎么办呢,总不能在cofe()函数里去掉吧。那如果有人想喝加糖咖啡、有人不想喝加糖咖啡如何是好,总不能写两个cofe()函数吧。 那我们带着问题看一下下面这段代码。
def add_sugar(func):
def add():
print('加糖',end='')
func()
return add
def cofe():
print('咖啡',end='')
cofe = add_sugar(cofe)
print("获得一杯",end='')
cofe()
####输出#####
获得一杯加糖咖啡
变量 cofe 指向了内部函数 add(),而内部函数 add() 中又会调用原函数 cofe(),因此,最后调用 cofe() 时,就会先打印‘加糖’,然后输出‘咖啡’。这里的函数 add_sugar() 就是一个装饰器,它把真正需要执行的函数cofe()包裹在其中,并且改变了它的行为,但是原函数 cofe() 不变。 下面我们来看一下更优雅的写法。
def add_sugar(func):
def add():
print('加糖',end='')
func()
return add
@add_sugar
def cofe():
print('咖啡',end='')
print("获得一杯",end='')
cofe()
#####输出#####
获得一杯加糖咖啡
这里的@叫做语法糖, @add_sugar就相当于前面的cofe = add_sugar(cofe)语句,只不过更加简洁。因此程序中建议用这种写法。 好了,让我们来回顾下我们的问题,如果有人想喝加糖咖啡、有人不想喝加糖咖啡如何是好。学了装饰器那不就很简单了,如果要喝加糖咖啡,我们把加糖的装饰器@add_sugar给加上不就好了,如果喝不加糖的,那就不加装饰器,这样我们就把这个问题给完美解决掉了。在不改变函数内部的前提了,给函数又添加了新的功能。 到目前为止,我们已经把最简单的装饰器学完了。下面我们在考虑一个问题,如果原函数 cofe() 中,有参数需要传递给装饰器怎么办?一个简单的办法,是可以在对应的装饰器函数 add() 上,加上相应的参数。
def add_sugar(func):
def add(type):
print('加糖',end='')
func(type)
return add
@add_sugar
def cofe(type):
print('{}咖啡'.format(type),end='')
cofe("美式")
print()
cofe("拿铁")
####输出#####
加糖美式咖啡
加糖拿铁咖啡
不过,新的问题来了。如果我另外还有一个函数(奶茶函数),也需要使用 add_sugar() 装饰器,但是这个新的函数有两个参数,又该怎么办呢? 通常情况下,我们会把*args和 **kwargs,作为装饰器内部函数 add() 的参数。*args和**kwargs,表示接受任意数量和类型的参数,因此加糖装饰器就可以写成下面的形式:
def add_sugar(func):
def add(*args, **kwargs):
print('加糖',end='')
func(*args, **kwargs)
return add @add_sugar
def cofe(type):
print('{}咖啡'.format(type),end='')
@add_sugar
def milk_tea(type,num):
print('{}杯{}奶茶'.format(num,type), end='')
cofe("美式")
print()
milk_tea("xx牌子","4")
####输出####
加糖美式咖啡
加糖4杯xx牌子奶茶
这样我们的咖啡和奶茶都可以加糖了。 前面我们讲的是函数的装饰器,下面我们来讲一下类作为装饰器。类装饰器主要依赖于函数__call__(),每当你调用一个类的实例时,函数__call__()就会被执行一次。
class Add_sugar:
def __init__(self, func):
self.func = func
self.add_suger = "加糖"
def __call__(self, *args, **kwargs):
print(self.add_suger,end='')
return self.func(*args, **kwargs)
@Add_sugar
def cofe():
print("咖啡")
cofe()
####输出#####
加糖咖啡
最后如果我们的咖啡既要加糖又要加冰,那我们该如何做呢?我们定义一个加冰的装饰器就好了呀。
def add_sugar(func):
def add():
print('加糖',end='')
func()
return add
def add_ice(func):
def add():
print('加冰',end='')
func()
return add
@add_sugar
@add_ice
def cofe():
print('咖啡',end='')
cofe()
####输出####
加糖加冰咖啡
从此以后,我们的咖啡想加什么就加什么。 欢迎大家留言和我交流。
Python装饰器-给你的咖啡加点料的更多相关文章
- 关于python装饰器
关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...
- python装饰器通俗易懂的解释!
1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...
- Python 装饰器学习
Python装饰器学习(九步入门) 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...
- python 装饰器修改调整函数参数
简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...
- python 装饰器学习(decorator)
最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...
- Python装饰器详解
python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...
- 关于python装饰器(Decorators)最底层理解的一句话
一个decorator只是一个带有一个函数作为参数并返回一个替换函数的闭包. http://www.xxx.com/html/2016/pythonhexinbiancheng_0718/1044.h ...
- Python装饰器由浅入深
装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...
- Python装饰器与面向切面编程
今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...
随机推荐
- 9.1 ps:查看进程
ps命令 用于列出执行ps命令的那个时刻的进程快照,就像用手机给进程照了一张照片.如果想要动态地显示进程的信息,就需要使用top命令,该命令类似于把手机切换成录像模式.因为ps命令的功能实在是太多了, ...
- python文件处理(对比和筛选)版本2
场景:对比两个txt文件的差异,将对比结果写入html,将不同部分写入另一个txt #!/user/bin/python #!coding=utf-8 # -*- coding: utf-8 -*- ...
- 在vue中如何使用WebSocket 以及nginx代理如何配置WebSocket
WebSocket WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信.浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输. 浏览器支持情况 现 ...
- Cisco Catalyst 9800-CL Wireless Controller for Cloud
面向云的思科 Catalyst 9800-CL 无线控制器,专为基于意图的网络全新打造. 版本: C9800-CL-universalk9.17.04.01 (29-Nov-2020) C9800-C ...
- 回顾Servlet
1.新建一个Maven工程当做父工程!pom依赖! <!-- 依赖 --> <dependencies> <dependency> <groupId>j ...
- Swagger的学习
Swagger 号称世界上最流行的Api框架; RestFul Api文档在线自动生成工具=>Api文档与API定义同步更新 直接运行,可以在线测试API接口 支持多种语言:(Java,Php. ...
- grasshopper之python电池执行逻辑
在grasshopper中,需要导入的包虽然不多,但是相当绕人,所要实现的操作往往找不到,暂时做个分类. 双击输入 python 电池: # 导入rhino 包 import Rhino #Rhino ...
- 面阿里P7,竟问这么简单的题目?
关于作者:程序猿石头(ID: tangleithu),来自十八县贫困农村(查看我的逆袭之路),BAT某厂P7,是前大疆(无人机)技术主管,曾经也在创业公司待过,有着丰富的经验. 本文首发于微信公众号, ...
- MindSpore应用目标
MindSpore应用目标 以下将展示MindSpore近一年的高阶计划,会根据用户的反馈诉求,持续调整计划的优先级. 总体而言,会努力在以下几个方面不断改进. 1. 提供更多的预置模型支持. 2. ...
- 整理AI性能指标
整理AI性能指标 Sorting out AI performance metrics 推理性能的最佳衡量标准是什么? 在人工智能加速器的世界里,对于给定的算法,芯片的性能经常以每秒万亿次的运算量(T ...