文章目录
- @[toc]
- 闭包
- 什么是装饰器
- 装饰器示例
- 不使用装饰器语法
- 使用装饰器语法
- 装饰器传参
- 带参数的装饰器
- 类装饰器
- 魔术方法\__call__()
- 类装饰器示例
- 带参数类装饰器
- property装饰器
- 分页操作
- 商品价格操作
文章目录
- @[toc]
- 闭包
- 什么是装饰器
- 装饰器示例
- 不使用装饰器语法
- 使用装饰器语法
- 装饰器传参
- 带参数的装饰器
- 类装饰器
- 魔术方法\__call__()
- 类装饰器示例
- 带参数类装饰器
- property装饰器
- 分页操作
- 商品价格操作
个人主页:丷从心·
系列专栏:Python基础
学习指南:Python学习指南
闭包
- 在学习装饰器之前,先来了解什么是闭包:【Python基础】闭包(2157字)
什么是装饰器
- 装饰器可以在不改变函数或类已有代码的前提下为其增加额外功能
- 装饰器本质上是一个高阶函数,它接受一个函数或类作为输入,并返回一个新的函数或类作为输出,这个新的函数或类具有扩展或修改原始函数或类行为的功能
装饰器示例
不使用装饰器语法
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
装饰的方法