Python之__call__ 函数和装饰器的作用

前言

  在Python代码中,定义类的时候经常会用到__call__()方法,具体有什么含义呢?;除了__call__()方法。python装饰器也经常被用到;接下来我们就聊一聊__call__()方法;和装饰器是如何实现的。

在这里插入图片描述
温故而知新,往期经典回顾:Python之numpy常用知识点总结

call 函数

  在Python中__call__ ()方法是一个特殊方法(也称为魔术方法或双下方法),它允许类的实例像函数那样被调用。当你尝试对一个对象使用圆括号()进行“调用”时,Python解释器会自动在该对象上查找__call__ ()方法,并调用它(如果存在);

代码介绍

  如何更直观的正确的理解上面的那句话呢,下面我们通过一个简单的程序来解释一下,下面这个程序就是正常的python类。里面有一个初始化代码,还有一个名字叫**test()**的函数;我们先实例化Adder类,再调用实例化的对象add() 发现,程序报错不能调用;

class Adder:
    def __init__(self, number):
        self.number = number

    def test(self, other):
        return self.number + other

add = Adder(5)
b = add(6)
print(b)     

结果:程序报错不能调用add 对象;

File "D:\Study\ml_practice\py\PyTorch_YOLOv1\test_xp.py", line 17, in <module>
    b = add(6)
TypeError: 'Adder' object is not callable

  如果我们在这个类中添加一个__call__ ()方法,会发生什么情况呢?

class Adder:
    def __init__(self, number):
        self.number = number

    def __call__(self, other):
        return self.number + other

add = Adder(5)
b = add(6)  # 对象add可以像函数一样调用(这就是__call__ ()函数的作用)
print(b)   # 

结果:

输出:11

从上述代码可以看出实例化的对象add() 可以正常调用了,这是因为我们在类Adder中声明了__call__()方法,它允许类的实例像函数那样被调用;通过上面的的例子就可以很清楚的知道__call__()的作用了;

Python装饰器

  Python装饰器是一种语法糖,用于在不改变原有函数代码的情况下,为函数添加额外的功能。
  装饰器本质上是一个函数,它接收一个函数作为参数,并返回一个新的函数,通常使用@语法糖来应用装饰器。

函数装饰器

  函数装饰器是最常见的装饰器形式,它接收一个函数并返回一个新的函数。这里有一个简单的例子:

def my_decorator(func):  
    def wrapper():  
        print("Something is happening before the function is called.")  
        func()  
        print("Something is happening after the function is called.")  
    return wrapper  
  
@my_decorator  
def say_hello():  
    print("Hello!")  
  
say_hello()  

输出:

Something is happening before the function is called.  
Hello!  
Something is happening after the function is called.

  在这个例子中,my_decorator是一个装饰器,它接收say_hello函数作为参数,并返回一个新的函数wrapper。当调用say_hello()时,实际上调用的是wrapper()函数,该函数在调用原始say_hello函数之前和之后添加了额外的打印语句。

带参数的函数装饰器

  如果你的函数需要参数,装饰器需要稍作修改以接受这些参数。

def my_decorator(func):  
    def wrapper(*args, **kwargs):  
        print("Something is happening before the function is called.")  
        func(*args, **kwargs)  
        print("Something is happening after the function is called.")  
    return wrapper  
  
@my_decorator  
def greet(name):  
    print(f"Hello, {name}!")  
    
@my_decorator
def add(a,b):
    print(2*a+b)
  
greet("Alice")
add(3,8)

结果:

#greet("Alice")结果
Before the function is called.
Hello,Alice
After the function is called.

#add(3,8)结果
Before the function is called.
14
After the function is called.

  在这个例子中,wrapper函数使用了*args和**kwargs来允许接收任意数量和类型的参数,并将它们传递给被装饰的函数func。

装饰器运用场景

装饰器的应用非常广泛,可以用于实现各种功能,例如:

  • 记录函数执行时间:通过在装饰器函数中记录函数执行的开始和结束时间,可以计算函数的执行时间。
  • 缓存函数结果:通过在装饰器函数中维护一个缓存,可以避免重复计算相同参数的函数结果,提高函数的执行效率。
  • 实现权限控制:通过在装饰器函数中检查用户的权限,可以控制用户对某些函数的访问权限。
  • 日志记录:通过在装饰器函数中记录函数的输入参数和返回值,可以方便地进行调试和错误排除。
  • 错误处理:通过在装饰器函数中捕获异常并进行处理,可以避免函数抛出异常导致程序崩溃。

Python装饰器是一种非常强大的语法糖,可以帮助我们实现各种功能,提高代码的复用性和可维护性。

案例实现:打印函数执行时间消耗

import time
# 注意:这个是带参数的装饰器
def calculate_execution_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        execution_time = end_time - start_time
        print(f"函数 {func.__name__} 的执行时间为: {execution_time:.2f} 秒")
        return result
    return wrapper

@calculate_execution_time
def my_function(a, b):
    # 假设这里是一个耗时的操作
    time.sleep(1)
    # 被装饰函数本身的功能
    return a+b

sum = my_function(1, 2)
print(sum)

结果:

函数 my_function 的执行时间为: 1.01sum:3

好啦,今天就分享到这里吧!关注我持续更新有价值的内容!
如有错误欢迎指正,如果帮到您请点赞加收藏哦!

以上程序可以关注我的微信公众号:回复"深度学习资料"领取深度学习相关资料(100本人工智能书籍),实时更新深度学习相关知识!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xp_fangfei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值