python画米老鼠_我终于弄懂了Python的装饰器(一)

此系列文档:

一、装饰器基础(什么是装饰器)

Python的函数是对象

要了解装饰器,您必须首先了解函数是Python中的对象。这具有重要的联系。

让我们来看一个简单的例子:

def shout(word="yes"):

return word.capitalize()+"!"

print(shout())

# 输出 : 'Yes!'

# 作为一个对象,您可以像其他对象一样将函数赋给变量

scream = shout

#注意我们不使用括号:我们没有调用函数

#我们将函数“shout”放入变量“scream”。

#这意味着您可以从“scream”中调用“shout”:

print(scream())

# 输出: 'Yes!'

#除此之外,这意味着您可以删除旧名称'shout',该功能仍可从'scream'访问

del shout

try:

print(shout())

except NameError as e:

print(e)

#输出: "name 'shout' is not defined"

print(scream())

# 输出: 'Yes!'复制代码

请记住这一点,我们将在不久后回头再说。

Python函数的另一个有趣特性是可以在另一个函数中定义它们!

def talk():

# 您可以在“talk”中动态定义一个函数...

def whisper(word="yes"):

return word.lower()+"..."

# ...并且可以立马使用它。

print(whisper())

#您每次调用“talk”,都会定义“whisper”,然后在“talk”中调用“whisper”。

talk()

# 输出:

# "yes..."

# 但是"whisper"不存在"talk"定义以外的地方:

try:

print(whisper())

except NameError as e:

print(e)

#输出 : "name 'whisper' is not defined"复制代码

函数参考

OK,应该还在看吧?现在开始有趣的部分...

您已经看到函数是对象。

因此,函数:

可以分配给变量

可以在另一个函数中定义

这意味着一个函数可以return另一个功能。

def getTalk(kind="shout"):

# 我们顶一个即时的函数

def shout(word="yes"):

return word.capitalize()+"!"

def whisper(word="yes") :

return word.lower()+"...";

# 然后我们返回它

if kind == "shout":

#我们不使用“()”,所以我们没有调用函数,我们正在返回这个函数对象

return shout

else:

return whisper

#获取函数并将其分配给变量: "talk"

talk = getTalk()

#您可以看到“talk”是一个函数对象:

print(talk)

#输出 :

#函数对象返回的内容:

print(talk())

#输出 : Yes!

#如果您感到困惑,甚至可以直接使用它:

print(getTalk("whisper")())

#outputs : yes...复制代码

还有更多的内容!

如果可以return一个函数,则可以将其中一个作为参数传递:

def doSomethingBefore(func):

print("I do something before then I call the function you gave me")

print(func())

doSomethingBefore(scream)

#输出:

#I do something before then I call the function you gave me

#Yes!复制代码

好吧,您只具备了解装饰器所需的所有信息。

您会看到,装饰器是“包装器(wrappers)”,这意味着它们使您可以在装饰函数之前和之后执行代码,而无需修改函数本身的代码内容。

手工进行装饰

您将知道如何进行手动操作:

#装饰器是讲另外一个函数作为参数的函数

def my_shiny_new_decorator(a_function_to_decorate):

# 在内部,装饰器动态定义一个函数:包装器(wrappers)。

# 此功能将被包装在原始功能的外部,以便它可以在代码之前和之后执行代码。

def the_wrapper_around_the_original_function():

# 在调用原始函数之前,将要执行的代码放在此处

print("Before the function runs")

#在此处调用函数(使用括号)

a_function_to_decorate()

# 在调用原始函数后,将要执行的代码放在此处

print("After the function runs")

#至此,“a_function_to_decorate”从未执行过。

#我们返回刚刚创建的包装函数。

#包装器包含函数和在代码之前和之后执行的代码。随时可以使用!

return the_wrapper_around_the_original_function

#现在,假设您创建了函数,但是不想再修改的函数。

def a_stand_alone_function():

print("I am a stand alone function, don't you dare modify me")

a_stand_alone_function()

#输出: I am a stand alone function, don't you dare modify me

#所以,您可以装饰它以扩展其行为。

#只需将其传递给装饰器,它将动态地包装在

#您想要的任何代码中,并为您返回准备使用的新功能:

a_stand_alone_function_decorated = my_shiny_new_decorator(a_stand_alone_function)

a_stand_alone_function_decorated()

#输出:

#Before the function runs

#I am a stand alone function, don't you dare modify me

#After the function runs复制代码

现在,您可能希望每次调用a_stand_alone_function时a_stand_alone_function_decorated都调用它。

这很简单,只需a_stand_alone_function用以下方法返回的函数覆盖my_shiny_new_decorator:

a_stand_alone_function = my_shiny_new_decorator(a_stand_alone_function)

a_stand_alone_function()

#输出:

#Before the function runs

#I am a stand alone function, don't you dare modify me

#After the function runs

#这正是装饰器的工作!复制代码

装饰器神秘化

这里展示一下使用装饰器的语法:

@my_shiny_new_decorator

def another_stand_alone_function():

print("Leave me alone")

another_stand_alone_function()

#输出:

#Before the function runs

#Leave me alone

#After the function runs复制代码

是的,仅此而已。@decorator只是实现以下目的的捷径:

another_stand_alone_function = my_shiny_new_decorator(another_stand_alone_function)复制代码

装饰器只是装饰器设计模式的pythonic变体。

Python中嵌入了几种经典的设计模式来简化开发(例如迭代器)。

当然,您可以累加装饰器:

def bread(func):

def wrapper():

print("''''''\>")

func()

print("")

return wrapper

def ingredients(func):

def wrapper():

print("#tomatoes#")

func()

print("~salad~")

return wrapper

def sandwich(food="--ham--"):

print(food)

sandwich()

#输出: --ham--

sandwich = bread(ingredients(sandwich))

sandwich()

#输出:

#''''''\>

# #tomatoes#

# --ham--

# ~salad~

#复制代码

使用Python装饰器语法:

@bread

@ingredients

def sandwich(food="--ham--"):

print(food)

sandwich()

#outputs:

#''''''\>

# #tomatoes#

# --ham--

# ~salad~

#复制代码

您设置装饰器事项的顺序是很重要的,如::

@ingredients

@bread

def strange_sandwich(food="--ham--"):

print(food)

strange_sandwich()

#outputs:

##tomatoes#

#''''''\>

# --ham--

#

# ~salad~复制代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值