【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装饰的方法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值