python装饰器
文章目录
1.闭包
1.1定义
在函数内部再定义一个函数并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
def hi(name="yasoob"):
print("hi")
def greet():
return "greet"
def welcome():
return "welcome"
print(greet())
print(welcome())
hi()
# 输出
# hi
# greet
# welcome
1.2从函数中返回函数
def hi(name="yasoob"):
def greet():
return "greet"
def welcome():
return "welcome"
if name == "yasoob":
return greet
else:
return welcome
a = hi()
print(a) #outputs: <function greet at 0x7f2143c01500>
print(a()) #outputs: greet
1.3将函数作为参数传递给另一个函数
def hi():
return "hi yasoob!"
def doSomethingBeforeHi(func):
print("before executing hi()")
print(func())
doSomethingBeforeHi(hi)
# outputs: before executing hi()
# hi yasoob!
2.装饰器
2.1装饰函数的装饰器
2.1.1函数装饰器
1.不带参数的
from functools import wraps
def decorator1(a_func):
def my_wrap():
print("decorator1_1")
a_func()
print("decorator1_2")
return my_wrap
def decorator2(a_func):
@wraps(a_func)
def my_wrap():
print("decorator2_1")
a_func()
print("decorator2_2")
return my_wrap
def decorator3(a_func):
@wraps(a_func)
def my_wrap():
print("decorator3_1")
return a_func()
print("decorator3_2")
return my_wrap
def decorator4(a_func):
@wraps(a_func)
def my_wrap(*args, **kwargs):
print("decorator4_1")
return a_func(*args, **kwargs)
return my_wrap
def a():
print("a")
@decorator1
def b():
print("b")
@decorator2
def c():
print("c")
@decorator3
def d():
return "d"
@decorator4
def e(e_str):
return e_str
if __name__ == '__main__':
# 1.将函数作为参数进行传递装饰
a = decorator1(a)
a()
# output
# decorator1
# a
# decorator1
# 2.使用@进行装饰
b()
# decorator2
# b
# decorator2
# 3.重写函数名字和注释文档
print(b.__name__) # output:my_wrap
print(c.__name__) # output:c
# 4.被装饰的函数有返回值:则不能不对其返回后的值进行装饰
print(d())
# decorator3_2
# decorator3_1
# d
# 5.被装饰的函数带有参数
print(e("e_str"))
注意:
1.@new_decorator等价与b = new_decorator(b)
2.functools.wraps重写函数名字和注释文档参数列表等等的功能
3.被装饰的函数有返回值,则不能对其返回后的值进行装饰
4.被装饰的函数带有参数
2.带参数的
from functools import wraps
def say_hello(country):
def wrapper(func):
@wraps(func)
def deco(*args, **kwargs):
if country == "china":
print("你好!")
elif country == "america":
print('hello')
else:
return "decorate error"
return func(*args, **kwargs)
return deco
return wrapper
# 小明,中国人
@say_hello("china")
def xiaoming():
pass
# jack,美国人
@say_hello("america")
def jack():
pass
if __name__ == '__main__':
xiaoming()
print("------------")
jack()
2.1.2类装饰器
1.不带参数的
绝大多数装饰器都是基于函数和闭包实现的,但这并非制造装饰器的唯一方式 python 对某个对象是否能通过装饰器( @decorator
)形式使用只有一个要求:decorator 必须是一个“可被调用(callable)的对象
class Logger(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print(f"[INFO]: the function {self.func.__name__}() is running...")
return self.func(*args, **kwargs)
@Logger
def say(something):
print(f"say {something}!")
if __name__ == '__main__':
say("hello")
# 输出
# [INFO]: the function say() is running...
# say hello!
2.带参数的
class Logger(object):
def __init__(self, level="INFO"):
self.level = level
def __call__(self, func):
def wrapper(*args, **kwargs):
print(f"[{self.level}]: the function {func.__name__}() is running...")
return func(*args, **kwargs)
return wrapper
@Logger(level='WARNING')
def say(something):
print(f"say {something}!")
if __name__ == '__main__':
say("hello")
# 输出
# [WARNING]: the function say() is running...
# say hello!
3.偏函数
import time
import functools
class DelayFunc:
def __init__(self, duration, func):
self.duration = duration
self.func = func
def __call__(self, *args, **kwargs):
print(f'Wait for {self.duration} seconds...')
time.sleep(self.duration)
return self.func(*args, **kwargs)
def eager_call(self, *args, **kwargs):
print('Call without delay')
return self.func(*args, **kwargs)
def delay(duration):
"""
装饰器:推迟某个函数的执行。
同时提供 .eager_call 方法立即执行
"""
# 此处为了避免定义额外函数,
# 直接使用 functools.partial 帮助构造 DelayFunc 实例
return functools.partial(DelayFunc, duration)
@delay(duration=2)
def add(a, b):
return a + b
if __name__ == '__main__':
print(add) # output:<__main__.DelayFunc object at 0x0000026CBDF8A730>
print(add(3, 5))
# output
# Wait for 2 seconds...
# 8
print(add.eager_call(3, 5))
# output
# Call without delay
# 8
print(add.func)# output <function add at 0x000001B85D5695E0>
2.2装饰类的装饰器
装饰器用在类上,并不是很常见,但只要熟悉装饰器的实现过程,就不难以实现对类的装饰
装饰器实现单例模式
instances = {}
def singleton(cls):
def get_instance(*args, **kwargs):
cls_name = cls.__name__
print('===== 1 ====')
if cls_name not in instances:
print('===== 2 ====')
instance = cls(*args, **kwargs)
instances[cls_name] = instance
return instances[cls_name]
return get_instance
@singleton
class User:
_instance = {}
def __init__(self, name):
print('===== 3 ====')
self.name = name
if __name__ == '__main__':
u1 = User("np1")
# == == = 1 == ==
# == == = 2 == ==
# == == = 3 == ==
u1.age = 20
u2 = User("np2")
# == == = 1 == ==
print(u2.age)
# 20
print(u1 is u2)
# True
参考
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix