前言
在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.01 秒
sum:3
好啦,今天就分享到这里吧!关注我持续更新有价值的内容!
如有错误欢迎指正,如果帮到您请点赞加收藏哦!
以上程序可以关注我的微信公众号:回复"深度学习资料"领取深度学习相关资料(100本人工智能书籍),实时更新深度学习相关知识!