函数装饰器装饰类

函数装饰器装饰类

不过尔尔 14 2023-12-03

介绍

函数装饰器是Python中一种强大的工具,它可以用来修改或增强函数的行为。通常函数装饰器用于装饰函数,但是也可以使用它来装饰类。因此可以使用它修改类的构造函数、添加类属性方法,或者对类的行为进行其他定制化的操作。

分类

1,无参装饰器

 def decorator(cls):
     # 定义一个新的类,继承自原始的类
     class Wrapper(cls):
         def __init__(self, *args, **kwargs):
             # 在构造函数中可以添加自定义逻辑
             print("CallMe之前执行")
             super().__init__(*args, **kwargs)
             print("CallMe之后执行")
 ​
     return Wrapper
 ​
 ​
 @decorator
 class CallMe(object):
     def __init__(self, name, phone):
         self.name = name
         self.phone = phone
         print("我被执行了!")
         
 ​
     def call_me(self):
         print(f"名字:{self.name},电话:{self.phone}")
 ​
 ​
 call = CallMe("萧炎", "9090")

输出:

 CallMe之前执行
 我被执行了!
 CallMe之后执行

decorator 函数是一个函数装饰器,它接受一个类作为被装饰对象,并返回一个新的类 Wrapper,该类继承自被装饰的类 cls。在 Wrapper 的构造函数中,我们添加了两条打印语句,以便在创建类的实例时显示消息。

然后使用 @decorator 装饰器语法来装饰 CallMe类,使其成为装饰后的类。当创建 CallMe 的实例时,会首先调用 Wrapper 的构造函数。

2,有参装饰器

 def decorator(arg1):
     def rapper(cls):
         # 定义一个新的类,继承自原始的类
         class Inner(cls):
             def __init__(self, *args, **kwargs):
                 print("CallMe之前执行")
                 super().__init__(*args, **kwargs)
                 # 在构造函数中可以使用参数 arg1
                 self.name = arg1
                 print("CallMe之后执行")
 ​
         return Inner
 ​
     return wrapper
 ​
 # 使用带参数的装饰器来装饰一个类
 @decorator("云韵")
 class CallMe(object):
     def __init__(self, name, phone):
         self.name = name
         self.phone = phone
         print("我被执行了!")
 ​
     def call_me(self):
         print(f"名字:{self.name},电话:{self.phone}")
 ​
 ​
 call = CallMe("萧炎", "9090")
 call.call_me()

输出:

 CallMe之前执行
 我被执行了!
 CallMe之后执行
 名字:云韵,电话:9090

decorator 函数是一个带参数的函数装饰器,它接受参数 arg1。然后,它返回一个内部装饰器函数 wrapper,这个函数接受一个类作为被装饰对象,并返回一个新的类 Inner

Inner 的构造函数中可以访问参数 arg1,并在创建类的实例时使用它。最后使用 @decorator("arg1_value") 来装饰 CallMe,传递参数给装饰器。

当创建 CallMe 的实例时,会首先调用 Inner 的构造函数,更新self.name的值。

3,原始写法

 from functools import wraps
 def logit(func):
     @wraps(func)
     def wrapper(*args, **kwargs):
         print('-' * 10)
         print('Calling: ' + func.__name__)
         value = func(*args, **kwargs)
         print('-' * 10)
         return value
     return wrapper
 ​
 @logit
 class Tester():
     def __init__(self):
         print('__init__ ended')
 ​
     def a_func(self):
         print('a_func ended')
 tester = Tester()
 tester.a_func()

输出:

 ----------
 Calling: Tester
 __init__ ended
 ----------
 a_func ended

总结

  1. 可以根据需求在装饰器中添加更复杂的逻辑,以修改类的行为。

  2. 函数装饰器为类提供了更灵活的定制选项,可以根据需求对类进行扩展和修改。

  3. 带参数的函数装饰器可以根据需要在装饰器和装饰的类之间传递不同的参数来实现更多的定制化。