【Python基础】之装饰器

             这是我初次接触装饰器,先从初学者的角度介绍装饰器,关于装饰器的应用场景举例,后面再补充。

1.装饰器的作用

  • 装饰器可以让一个函数在不做任何变动的情况下新增额外的功能。

如下代码,func_name函数是打印传入函数的函数名,f1函数就是打印一个字符串。

def func_name(func):
    """打印传入函数的函数名"""
    print(func.__name__)

def f1():
    print("这是待装饰的函数f1")

现在要求,每次调用一个函数的时候,都要打印该函数的函数名,那么我们可以在f1函数内部作如下修改:

def f1():
    func_name(f1)
    print("这是待装饰的函数")

f1() #f1 这是待装饰的函数

看似很简单,但是实际应用场景中可能有几十个函数需要作这样的修改,都在函数内部作改动是很麻烦的,也容易出错,那么我们可以利用装饰器在f1函数的外部进行修改。

2.写一个装饰器

如下代码就是对1中的f1函数作一个修改。可以看到我们定义了两个函数func_name和函数f1,其中我们用func_name函数装饰了函数f1。

那么在装饰的过程中,f1发生了怎么样的变化呢。首先我们要定义一个装饰器func_name,然后在待装饰的函数正上方输入@func_name(注意,这里是@+函数名,不带括号)。

当我们调用函数f1()时,一共发生了三件事,

  • 第一,执行func_name函数,并把@下面一行的函数名称(注意,不带括号,是函数名)传给func_name,这时func_name会返回函数名称wrap(注意,是函数名,不带括号),
  • 第二步,将func_name返回的函数名称wrap赋值给f1,即f1 = func_name(f1), 而func_name(f1)=wrap,所以这时,f1 = wrap(),
  • 第三步,执行f1()函数,即wrap()函数,但是现在wrap()中的func()函数还是原来传入func_name的f1函数。
def func_name(func):
    def wrap():
        print(func.__name__)
        func()
    return wrap

@func_name
def f1():
    print("这是待装饰的函数")

f1()# f1 这是待装饰的函数

3.带参数的装饰器

如果f1带参数呢?比如下方的f1,有一个参数args

def f1(args):
    print(args)
    print("这是待装饰的函数")

那么我们可以在装饰器中的wrap()和func()中也加入相同的参数。

def func_name(func):
    def wrap(args): #加入参数
        print(func.__name__)
        func(args) #加入参数
    return wrap

@func_name
def f1(args):
    print(args)
    print("这是待装饰的函数")

f1("我是参数")
"""
输出:
f1
我是参数
这是待装饰的函数
"""

但是如果我们需要用func_name装饰十几个函数,而十几个函数传入的参数格式、格式都不相同,怎么办呢?这时我们可以在wrap()和func()中传入动态参数*args, **kwargs,这样勿论待装饰的函数传入多少参数,装饰器都能够正确接受。

有关动态参数见:https://blog.csdn.net/lincoco49/article/details/89364034

def func_name(func):
    def wrap(*args, **kwargs):#动态参数
        print(func.__name__)
        func(*args, **kwargs) #动态参数
    return wrap


@func_name
def f1(args):#一个形参
    print(args)
    print("这是待装饰的函数")

@func_name
def f2(a, b): #两个形参
    ret = a+b
    print(ret)

f1("我是参数")
"""
f1
我是参数
这是待装饰的函数
"""

f2(1,1)
"""
f2
2
"""

4.写装饰器易错总结:

  • @后面跟的是函数名,不加括号
  • 装饰器返回的也是一个函数名,不加括号,加了括号就会执行函数了

猜你喜欢

转载自blog.csdn.net/lincoco49/article/details/89552500