【Python基础】装饰器(3848字)

因上努力

个人主页:丷从心·

系列专栏:Python基础

学习指南:Python学习指南

果上随缘


闭包


什么是装饰器

  • 装饰器可以在不改变函数或类已有代码的前提下为其增加额外功能
  • 装饰器本质上是一个高阶函数,它接受一个函数或类作为输入,并返回一个新的函数或类作为输出,这个新的函数或类具有扩展或修改原始函数或类行为的功能

装饰器示例

不使用装饰器语法
def debug(func_obj):
    def wrapper():
        print(f'[DEBUG]: {func_obj.__name__}')

        func_obj()

    return wrapper


def say_hello():
    print('hello')


say_hello = debug(say_hello)
say_hello()
[DEBUG]: say_hello
hello
  • debug(say_hello)的返回值是一个函数,使用变量say_hello进行接收,于是函数say_hello()被增加了功能
使用装饰器语法
  • 装饰器通过使用@符号紧跟在函数或类定义之前来使用
def debug(func_obj):
    def wrapper():
        print(f'[DEBUG]: {func_obj.__name__}')

        func_obj()

    return wrapper


@debug
def say_hello():
    print('hello')


say_hello()
[DEBUG]: say_hello
hello
  • 本质上@debug的作用就是执行了say_hello = debug(say_hello),为函数say_hello 增加了功能

装饰器传参

  • 如果被装饰的函数带有参数,调用时需要进行传参
def debug(func_obj):
    def wrapper(*args, **kwargs):
        print(f'[DEBUG]: {func_obj.__name__}')

        func_obj(*args, **kwargs)

    return wrapper


@debug
def say(message):
    print(message)


say('Hello, world!')
[DEBUG]: say
Hello, world!

带参数的装饰器

def level(lev):
    def logger(func):
        def wrapper(*args, **kwargs):
            print(f'[{lev}]: {func.__name__}')

            func(*args, **kwargs)

        return wrapper

    return logger


@level('INFO')
def say(message):
    print(message)
[INFO]: say
Hello, world!
  • 本质上@level('INFO')的作用就是执行了say = level('INFO')(say),为函数say增加了功能
def level(lev):
    def logger(func):
        def wrapper(*args, **kwargs):
            print(f'[{lev}]: {func.__name__}')

            func(*args, **kwargs)

        return wrapper

    return logger


def say(message):
    print(message)


say = level('INFO')(say)
say('Hello, world!')
[INFO]: say
Hello, world!

类装饰器

魔术方法_call_()
  • 一个类实现了魔术方法__call__()时,当对象被调用时会自动触发__call__()方法
class Test:
    def __call__(self, *args, **kwargs):
        print('我被触发了...')


test = Test()
test()
我被触发了...
类装饰器示例
class Debug:
    def __init__(self, func_obj):
        self.func_obj = func_obj

    def __call__(self, *args, **kwargs):
        print(f'[DEBUG]: {self.func_obj.__name__}')

        self.func_obj(*args, **kwargs)


@Debug
def say(message):
    print(message)


say('Hello, world!')
[DEBUG]: say
Hello, world!
  • 本质上@Debug的作用就是执行了say = Debug(say),为函数say增加了功能
带参数类装饰器
class Logger:
    def __init__(self, level='info'):
        self.level = level

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            print(f'[{self.level}]: {func.__name__}')

            func(*args, **kwargs)

        return wrapper


@Logger(level='ERROR')
def say(message):
    print(message)


say('Hello, world!')
  • 本质上@Logger(level='ERROR')的作用就是执行了say = Logger(level='ERROR')(say),为函数say增加了功能
property装饰器
  • property装饰的方法可以看作一个实例属性,在调用时无需()
分页操作
class Page:
    def __init__(self, page_number):
        self.page_number = page_number
        self.page_size = 10

    @property
    def start(self):
        val = (self.page_number - 1) * self.page_size

        return val + 1

    @property
    def end(self):
        val = self.page_number * self.page_size

        return val


page = Page(2)

print(f'第 {page.page_number} 页, 显示第 {page.start} - {page.end} 条内容')
商品价格操作
class Goods:
    def __init__(self, ori_price):
        self.ori_price = ori_price

    @property
    def price(self):
        print('价格正在获取中...')

        return self.ori_price

    @price.setter
    def price(self, new_price):
        print('价格正在修改中...')

        self.ori_price = new_price

    @price.deleter
    def price(self):
        print('价格正在删除中...')


goods = Goods(100)

goods_price = goods.price
print(goods_price)

goods.price = 200
print(goods.ori_price)

del goods.price
  • 对被@property装饰的属性进行修改时,会触发被@price.setter装饰的方法
  • 删除被@property装饰的属性时,会触发被@price.deleter装饰的方法

相关推荐

  1. python函数装饰基础

    2024-05-13 07:40:09       39 阅读
  2. python装饰基础

    2024-05-13 07:40:09       34 阅读
  3. python装饰嵌套基础

    2024-05-13 07:40:09       36 阅读
  4. 装饰基础知识

    2024-05-13 07:40:09       34 阅读
  5. Python装饰

    2024-05-13 07:40:09       41 阅读
  6. Python装饰

    2024-05-13 07:40:09       40 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-05-13 07:40:09       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-13 07:40:09       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-13 07:40:09       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-13 07:40:09       18 阅读

热门阅读

  1. Unity3D安装图文详细步骤

    2024-05-13 07:40:09       10 阅读
  2. 第十三届蓝桥杯国赛

    2024-05-13 07:40:09       9 阅读
  3. OpenCV 光流法总结

    2024-05-13 07:40:09       7 阅读
  4. boto3库调用AWS大模型的封装类

    2024-05-13 07:40:09       11 阅读
  5. 排序算法 下

    2024-05-13 07:40:09       13 阅读
  6. Vue简介

    2024-05-13 07:40:09       12 阅读
  7. Yarn使用

    2024-05-13 07:40:09       9 阅读
  8. TensorFlow基于anaconda3快速构建

    2024-05-13 07:40:09       9 阅读
  9. redis面试

    2024-05-13 07:40:09       9 阅读
  10. MySQL数据库基础功能

    2024-05-13 07:40:09       8 阅读
  11. linux程序分析命令(一)

    2024-05-13 07:40:09       9 阅读