装饰器的简单使用

装饰器,其实装饰器就是一个闭包,装饰器是闭包的一种应用。什么是装饰器呢,简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。使用时,再需要的函数前加上@debug即可。

def debug(func):
    def wrapper():
        print("[DEBUG]: enter {}()".format(func.__name__))
        return func()
    return wrapper

@debug
def hello():
    print("hello")

hello()
-----------------------------
>>>[DEBUG]: enter hello()
>>>hello

例子中的装饰器给函数加上一个进入函数的debug模式,不用修改原函数代码就完成了这个功能,可以说是很方便了。

<think>我们被要求提供Python装饰器简单使用示例。根据引用[2]和[4],类装饰器使用类来实现装饰器功能的一种方式。类装饰器通常通过定义`__init__`和`__call__`方法来实现。类装饰器的基本结构:-`__init__`方法:接收被装饰的函数(如果装饰的是函数)或类(如果装饰的是类)。-`__call__`方法:当被装饰的函数被调用时,实际上会调用装饰器实例的`__call__`方法。在`__call__`方法中,我们可以添加额外的功能,并调用原函数。下面我们给出一个简单的类装饰器示例,该装饰器用于记录函数的执行次数(引用[4]中也有类似示例)。示例:使用装饰器统计函数调用次数```pythonclassCountCalls:def__init__(self,func):self.func=funcself.num_calls=0#用于记录函数被调用的次数def__call__(self,*args,**kwargs):self.num_calls+=1print(f"函数{self.func.__name__}被调用了第{self.num_calls}次")returnself.func(*args,**kwargs)#使用装饰器@CountCallsdefsay_hello():print("Hello!")#测试say_hello()#输出:函数say_hello被调用了第1次然后输出:Hello!say_hello()#输出:函数say_hello被调用了第2次然后输出:Hello!```解释:-当我们将`@CountCalls`放在函数`say_hello`定义之前时,相当于执行了:`say_hello=CountCalls(say_hello)`。-这样,`say_hello`实际上成为了`CountCalls`类的一个实例。-当我们调用`say_hello()`时,实际上调用了该实例的`__call__`方法,在这个方法中我们增加了调用次数并打印,然后调用原来的函数。另一个示例:使用装饰器实现函数执行时间记录```pythonimporttimeclassTimer:def__init__(self,func):self.func=funcdef__call__(self,*args,**kwargs):start_time=time.time()result=self.func(*args,**kwargs)#执行原函数end_time=time.time()print(f"函数{self.func.__name__}执行耗时:{end_time-start_time:.4f}秒")returnresult@Timerdefslow_function(duration):time.sleep(duration)return"完成"#测试print(slow_function(1))#先等待1秒,然后输出执行时间,最后输出"完成"```注意:类装饰器也可以装饰类,但这里我们主要关注装饰函数的情况。引用[2]提到,类装饰器的执行顺序是从下往上(最靠近类的先执行),但这里我们只使用了一个装饰器。总结:类装饰器通过类的方式实现,利用`__call__`方法使得实例可以像函数一样被调用,从而在调用前后插入额外的逻辑。根据要求,我们生成相关问题。###相关问题:1.类装饰器和函数装饰器在实现上有哪些主要区别?2.如何用类装饰器装饰一个类(而不是函数)?3.类装饰器中的`__call__`方法有什么作用?4.多个类装饰器叠加使用时,执行顺序是怎样的?</think>### Python装饰器简单使用示例 类装饰器使用类实现装饰器功能的一种方式,通过定义`__init__`和`__call__`方法来实现。下面是两个简单实用的示例: #### 示例1:函数调用计数器 ```python class CountCalls: def __init__(self, func): self.func = func self.call_count = 0 # 初始化计数器 def __call__(self, *args, **kwargs): self.call_count += 1 # 每次调用增加计数 print(f"函数 {self.func.__name__} 已被调用 {self.call_count} 次") return self.func(*args, **kwargs) @CountCalls def greet(name): print(f"你好, {name}!") greet("小明") # 输出: 函数 greet 已被调用 1 次 → 你好, 小明! greet("小红") # 输出: 函数 greet 已被调用 2 次 → 你好, 小红! ``` #### 示例2:函数执行时间记录器 ```python import time class Timer: def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): start = time.perf_counter() # 记录开始时间 result = self.func(*args, **kwargs) # 执行原函数 elapsed = time.perf_counter() - start # 计算耗时 print(f"函数 {self.func.__name__} 执行耗时: {elapsed:.4f}秒") return result @Timer def calculate_sum(n): return sum(range(n+1)) print(calculate_sum(1000000)) # 输出: 函数 calculate_sum 执行耗时: 0.0453秒 → 500000500000 ``` #### 类装饰器关键点: 1. **初始化**:`__init__`方法接收被装饰的函数 2. **调用逻辑**:`__call__`方法定义装饰行为 3. **状态保持**:类实例可存储状态(如计数器值) 4. **执行顺序**:装饰器从下往上执行(最靠近函数的先执行)[^2] 类装饰器相比函数装饰器更适合需要**保持状态**的场景,如计数器、缓存等[^4]。通过`__call__`方法实现函数调用拦截,在调用前后添加自定义逻辑。 ### 相关问题: 1. 类装饰器中如何访问被装饰函数的元信息(如函数名)? 2. 带参数的类装饰器如何实现? 3. 类装饰器与函数装饰器在性能上有何差异? 4. 如何使用装饰器实现函数结果缓存(Memoization)?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值