在python的学习过程中,随着我们学习逐渐深入,不可避免会遇到装饰器的使用。使用装饰器,不仅可以使代码简洁、清晰,使开发方边,关键是可以大幅增加我们代码的逼格。我在这儿,分享一下我学习python装饰器的心得体会。
我对装饰器的理解就是在不影响原函数的前提下,对已有函数进行调用,并扩展一系列其他功能。因此,为了更深刻的学习装饰器,有必要与函数调用函数之间进行对比比较。函数调用函数比较简单,为了不失一般性,我们假设函数有各种参数,如下:
程序示例:def print_tips_func(func, *args, **kwargs):
print("function {} is running..".format(func.__name__))
return func(*args, **kwargs)
def func1(*args, **kwargs):
print("I am func1, I'm running....")
print("my parameters is", args, kwargs)
调用
print_tips_func(func1, 2, height=3)
运行结果:
function func1 is running..
I am func1, I'm running....
my parameters is (2,) {'height': 3}
以上是我们想要扩展函数功能时,采用函数调用函数方式的示例,学过python的同学应该都会使用。而与之等价的装饰器的用法是什么样的呢?如下:
程序示例:这里需要注意一点,这里写的装饰器自身没有参数传递,是无参数装饰器,使用的时候,"@ print_tips_decorate"这一句话,不能加括号。这是由于@的语法规定,自动将@装饰的函数作为参数传递给我们的print_tips_decorate装饰器函数。
def print_tips_decorate(func):
def wraps(*args, **kwargs):
print("function {} is running..".format(func.__name__))
return func(*args, **kwargs)
return wraps
@ print_tips_decorate
def func2(*args, **kwargs):
print("I am func2, I'm running....")
print("my parameters is", args, kwargs)
调用
func2(1, height=2)
运行结果:
function func2 is running..
I am func1, I'm running....
my parameters is (1,) {'height': 2}
由上面的对比,我们会发现两者的效果是一样的,但是我们使用装饰器时,函数扩展以后,不会对函数有任何影响,且不会更改我们需要调用的函数名,通过使用装饰器,我们可以对同一系列功能的函数进行进一步扩展而不需要更改函数本身的内容,更加利于开发而且方便。
二、当装饰器函数需要参数时…学会了装饰器的基本用法后,我们会发现有时候我们不仅仅是被装饰的函数需要参数传递,装饰函数本身有时也需要传递参数,比如我们上文写的打印提示信息装饰器函数,如果我们需要不同种类的提示信息,仅仅依靠装饰器内部的修改不能满足我们的要求,我们就需要对装饰器函数耶传递参数,怎么做到呢?如下:
程序示例:与上面的对比,我们会发现,装饰器函数又增加了一"层",正是这外面的一层,让我们可以在调用@符号时,将参数传递到装饰器中去。
def print_tips_decorate_param(tips=""):
def print_tips_decorate(func):
def wraps(*args, **kwargs):
print(tips)
return func(*args, **kwargs)
return wraps
return print_tips_decorate
@ print_tips_decorate_param("我就是老天最宠爱的崽~")
def func3(*args, **kwargs):
print("I am func3, I'm running....")
print("my parameters is", args, kwargs)
调用
func3("Hello", world="Earth")
运行结果:
我就是老天最宠爱的崽~
I am func1, I'm running....
my parameters is ('Hello',) {'world': 'Earth'}
总结
感觉自己对于装饰器还是停留在粗浅的使用上面,对于原理了解的不是明白。感觉站在了大佬的肩膀上(根据大佬的博客学习的),但是还是没有大佬看得远,你说气人不气人…
调试全代码最后,贴一下我编写博客时,调试使用的全代码,以供参考。
def print_tips_decorate(func):
def wraps(*args, **kwargs):
print("function {} is running..".format(func.__name__))
return func(*args, **kwargs)
return wraps
@ print_tips_decorate
def func2(*args, **kwargs):
print("I am func2, I'm running....")
print("my parameters is", args, kwargs)
def print_tips_decorate_param(tips=""):
def print_tips_decorate(func):
def wraps(*args, **kwargs):
print(tips)
return func(*args, **kwargs)
return wraps
return print_tips_decorate
@ print_tips_decorate_param("我就是老天最宠爱的崽~")
def func3(*args, **kwargs):
print("I am func3, I'm running....")
print("my parameters is", args, kwargs)
def print_tips_func(func, *args, **kwargs):
print("function {} is running..".format(func.__name__))
return func(*args, **kwargs)
def func1(*args, **kwargs):
print("I am func1, I'm running....")
print("my parameters is", args, kwargs)
if __name__ == "__main__":
func2(1, height=2)
print("--"*20)
print_tips_func(func1, 2, height=3)
print("--"*20)
func3("Hello", world="Earth")