[Python] 过程型程序设计进阶(三):Python函数装饰器

  • 概念:
    修饰器也是一个函数,接受一个函数或方法作为其唯一的参数,并返回一个修饰后的函数或方法。
  • 作用:对函数或方法进行一次修饰和包裹。

之前学习过@property修饰器。接下来学习如何自定义一个修饰器。

自定义函数修饰器

自定义一个装饰器,一般是通过局部方法实现,也即在方法中定义的方法。下面给出两种实现自定义修饰器的方法,一种是手动实现装饰器功能,另一种是通过functools模块的wraps修饰器进行实现。

方式一
# 自定义修饰器
def my_decorator2(function):
    def wrapper(*args, **kwargs):
        print("called my_decorator2 function-----2")
        return function(*args, **kwargs)
    # 将名称和docstring设置为原来函数的
    wrapper.__name__ = function.__name__
    wrapper.__doc__ = function.__doc__
    return wrapper

# 将example_2函数作为唯一参数传给了my_decorator2()
@my_decorator2
def example_2():
    """DocString:This is a decorator by custome """
    print("called example2 function----2")

example_2()
print(example_2.__name__)
print(example_2.__doc__)
"""
输出结果:
called my_decorator2 function-----2
called example2 function----2
example_2
DocString:This is a decorator by custome 
"""
方式二,使用functool.wrap()函数:
# functools模块用于高阶函数:作用于或返回其他函数的函数
from functools import wraps
# functools.wraps()函数常用于在定义一个修饰函数时作为函数修饰器调用functool.update_wrapper()方法
# functools.wraps修饰器进行包裹,确保了wrapper()函数的__name__和__doc__相等
def my_decorator(function):
    @wraps(function)
    def wrapper(*args, **kwargs):
        print("Calling decorator function---1")
        return function(*args, **kwargs)
    return wrapper

@my_decorator
def example():
    """DocString:This is a decorator by functool.wrapper """
    print("Calling example function---1")
example()
print(example.__name__)
print(example.__doc__)
"""
输出结果:
Calling decorator function---1
Calling example function---1
example
DocString:This is a decorator by functool.wrapper 
"""
  • 实现原理:
    修饰器函数定义了一局部函数wrapper(),wrapper()调用了原始函数,并进行了特殊处理,最后返回该wrapper,同时为了有更好的自省性,将wrapper的__name____doc__设置为原始函数的对应值.

在文章开头说了,修饰器函数只支持唯一一个参数,就是被修饰的函数,有时候,给修饰器函数提供参数也是有必要的,那么如何做呢?可以在局部方法中再定义一个局部方法,如:

def bound(arg1, arg2):
    def wrap(func):
        @functools.wraps(func)
        def wrap_wrap(*args, **kwargs):
            result = func(*args, **kwargs)
            if result < arg1:
                # .....
                pass
            elif result > arg2:
                # ....
                pass
            return result
        return wrap_wrap
    return wrap

@classmethod装饰器

@classmethod:将方法转换为类方法
类方法将类作为第一个隐式参数接受,声明格式如下:

class C:
    @classmethod
    def f(cls, arg1, arg2, ...): ...

调用该方法时,有两种方式:

C.f()或

C().f()
  • 作用:调用classmethod方法时,会将类作为第一个参数(而不是类的对象,尽管可以通过对象调用该方法),因此可以在该方法使用类和类的属性,而不是类对象的属性。
    如果是派生类调用类方法,则第一个参数为派生类对象将作为第一个隐式参数。

@staticmethod装饰器

@staticmethod:将方法转换为静态方法
Python中的静态方法和java、c++中类似,调用时可以通过类来调用,也可以使用类对象调用:

class C:
    @staticmethod
    def f(arg1, arg2, ...): ...

C.f()
C().f()
  • 作用:调用staticmethod方法时,不会传入一个类的实例(尽管可以这么调用),因此该方法中无法访问类对象的属性。

@property

property修饰器作用可理解为python类的的getter/setter,在之前文章中总结过了,点击查看

猜你喜欢

转载自blog.csdn.net/fightfightfight/article/details/79930601
今日推荐