0
点赞
收藏
分享

微信扫一扫

Python 修饰器 - 胖子老板:年终了,是时候给蓝利群加1元了。


仅供学习,转载请注明出处

装饰器

装饰器是程序开发中经常会用到的一个功能,用好了装饰器,开发效率如虎添翼,所以这也是Python面试中必问的问题,但对于好多初次接触这个知识的人来讲,这个功能有点绕,自学时直接绕过去了,然后面试问到了就挂了,因为装饰器是程序开发的基础知识,这个都不会,别跟人家说你会Python, 看了下面的文章,保证你学会装饰器。

在学习装饰器之前,首先要懂得闭包,如果还不懂,那么请点击​​这里​​,进行阅读一下。

那么理解完毕了闭包的功能之后,下面我们来看看一个示例,来理解一下装饰器。

装饰器示例:胖子老板头疼给每个商品价格都加1元

年终到了,大部分人都会到店铺买点小礼物之类的东西去送人。此时此景,胖子老板就想把店铺的付费系统价格都临时加1元,这样的话,大家也不介意。

但是由于商品计算价格的函数太多啦,一个个去写,感觉好烦。
下面来看看。

In [37]: def Smoke_Price():
...: return 17
...:

In [38]: def Binlang_Price():
...: return 10
...:

In [39]: sp = Smoke_Price

In [41]: sp()
Out[41]: 17

In [42]: bl = Binlang_Price

In [43]: bl()
Out[43]: 10

除了这两个商品,还有很多很多的商品,那么怎么来改写呢?

首先用闭包的方式来看看能否实现:

In [44]: def add_price(price):
...: def Smoke_Price():
...: return 17 + price
...: return Smoke_Price
...:
...:

In [45]: ap = add_price(1)

In [46]: ap()
Out[46]: 18

In [47]:

实现是实现了,但是要每次都写一个这样的闭包,好烦呢。那不就是每个商品的计算价格的函数都要写一遍?
有没有更加好的方式呢?

使用修饰器的方式

def add_price(Smoke_price):
def call_func():
print("------ 增加了修饰器 ------")
return Smoke_price() + 1
return call_func

@add_price
def Smoke_price():
return 17

sp = Smoke_price()

print(sp)

运行看看:

F:\pythonProject\test>python test2.py
------ 增加了修饰器 ------
18

F:\pythonProject\test>

从上面的结果来看,只要加上 ​​@add_price​​ 就可以实现了。

那么这里面的实现原理是怎么样的呢?

In [1]: def Smode_price():
...: return 17
...:

In [2]: def add_price(Smode_price):
...: def call_func():
...: return Smode_price() + 1
...: return call_func
...:

In [3]: sp = add_price(Smode_price)

In [4]: sp()
Out[4]: 18

In [5]:

上面函数的调用过程等价于使用add_price再次调用Smoke_price。

从上面的例子中看出,在写装饰器的时候,我将价格 1 元写死了,那么如果要写价格为 2元 呢?是不是又要写一个装饰器?

下面来写一个带参数的装饰器示例

def set_price(price):
def add_price(Smoke_price):
def call_func():
print("------ 增加了修饰器 ------")
return Smoke_price() + price
return call_func
return add_price

@set_price(1) ## 写入装饰器的参数 price = 1
def Smoke_price():
return 17

sp = Smoke_price()

print(sp)

只要在​​add_price(Smoke_price)​​​外部再包一层闭包,淡定写上参数price,这样就可以啦。
运行如下:

F:\pythonProject\test>python test2.py
------ 增加了修饰器 ------
18

上面已经完成了大部分装饰器的功能了,此情此景下,胖子老板想要给Smoke_price写几个参数,用来计算打折,又想要给Binlang_price写几个参数,如果中奖了,那么就直接不需要给钱了。

那么这个需求该怎么去实现呢?

首先先看看更改参数后的方法

## 修改Smoke_price方法,添加折扣discount参数
In [1]: def Smoke_price(discount):
...: price = 17
...: return price * discount
...:

In [3]: sp = Smoke_price(0.8)

In [4]: sp
Out[4]: 13.600000000000001

In [5]:

## 设置isWin参数,判断购买槟榔是否中将,中奖就不用付款啦。
In [5]: def Binlang_price(isWin):
...: if isWin:
...: return 0
...: else:
...: return 10
...:

## 设置槟榔中奖,为True
In [6]: bp = Binlang_price(True)

In [9]: print(bp)
0

## 设置槟榔没有中奖,为Flase
In [11]: bp = Binlang_price(False)

In [12]: bp
Out[12]: 10

In [13]:

从上面看出,​​Smoke_price(discount)​​​和 ​​Binlang_price(isWin)​​两个方法,如果要被修饰器调用,那么当然在修饰器中,调用这两个方法的时候,也要将参数传入。

此时就可以使用 ​​*args,**kwargs​​ 两个可变的形参来处理。

下面来实现一下增加参数后的修饰器:

def set_price(price):
def add_price(func):
def call_func(*args,**kwargs):
print("------ 增加了修饰器 ------")
return func(*args,**kwargs) + price
return call_func
return add_price

# 计算香烟的价格
@set_price(1)
def Smoke_price(discount):
price = 17
return price * discount

sp = Smoke_price(0.8)

print("蓝利群的价格=%0.2f" % sp)

# 计算槟榔的价格
@set_price(1)
def Binlang_price(isWin):
if isWin:
return 0
else:
return 10

bp = Binlang_price(True)

print("槟榔的价格=%d" % bp)

运行如下:

F:\pythonProject\test>python test2.py
------ 增加了修饰器 ------
蓝利群的价格=14.60
------ 增加了修饰器 ------
槟榔的价格=1

F:\pythonProject\test>

满足了这些要求了之后,胖子老板还想计算多一个运费,然后直接在原来的方法中返回一个 运费 + 价格 的总数,这个又该怎么处理呢?

使用多个修饰器,来解决这个问题

## 设置计算运费
def freight(func):
# 运费10元
freight_price = 10
def call_func(*args,**kwargs):
print("---------1 计算添加运费 --------------")
return func(*args,**kwargs) + freight_price
return call_func


## 设置价格加价
def set_price(price):
def add_price(func):
def call_func(*args,**kwargs):
print("------ 2.增加了修饰器 ------")
return func(*args,**kwargs) + price
return call_func
return add_price

# 计算香烟的价格
@freight
@set_price(1)
def Smoke_price(discount):
price = 17
return price * discount

sp = Smoke_price(0.8)

print("蓝利群的价格=%0.2f" % sp)

# 计算槟榔的价格
@freight
@set_price(1)
def Binlang_price(isWin):
if isWin:
return 0
else:
return 10

bp = Binlang_price(True)

print("槟榔的价格=%d" % bp)

运行如下:

F:\pythonProject\test>python test2.py
---------1 计算添加运费 --------------
------ 2.增加了修饰器 ------
蓝利群的价格=24.60
---------1 计算添加运费 --------------
------ 2.增加了修饰器 ------
槟榔的价格=11

F:\pythonProject\test>

好啦,从上面来看,直接写多一个修饰器,用来计算增加运费即可。
其实修饰器就是多层闭包函数的调用,执行的顺序则是从上至下逐个修饰器执行的。





Python 修饰器 - 胖子老板:年终了,是时候给蓝利群加1元了。_php


关注微信公众号,回复【资料】、Python、PHP、JAVA、web,则可获得Python、PHP、JAVA、前端等视频资料。

举报

相关推荐

0 条评论