python中的对象 
1 2 3 4 5 6 7 8 9 10 11 12 def  apple ():    print ("there is an apple" ) apple apple() obj = apple obj() 
 
注意这里apple 和 apple() 的区别
 
apple(函数对象) 定义 :apple 是函数对象的引用。 
 
在 Python 中,函数是第一类对象(First-class object),意味着它们可以被赋值给变量、作为参数传递、作为返回值返回等。 
apple 本质上是一个指向函数对象的引用,它存储了函数的定义(包括函数名、参数列表、函数体等信息)。 
调用 type(apple) 返回 <class ‘function’>,说明 apple 是一个函数类型的对象。 
 
apple()(函数调用) 定义 :apple() 表示调用 apple 函数。 
 
当在函数名后加上括号 () 时,Python 解释器会执行该函数的代码块。 函数调用的过程包括:
创建一个新的作用域(局部命名空间)。 
执行函数体中的代码。 
如果函数中有 return 语句,则返回指定的值;否则默认返回 None。 
在这个例子中,apple() 执行了函数体中的 print(“there is an apple”),因此打印了消息。 
 
 
 
定义一个log函数能够记录日志 
直接在log函数中打印日志,并且执行传入的函数func 
但这样会将原来直接执行apple()改为需要执行log(apple) 
 
1 2 3 4 5 6 7 8 def  apple ():    print ("there is an apple" ) def  log (func ):    print ("this is log" )     func() log(apple) 
 
保证继续apple() 1 2 3 4 5 6 7 8 9 def  apple ():    print ("there is an apple" ) def  log (func ):    print ("this is log" )     func() apple = log(apple)  apple() 
 
注意这里log(apple)是函数调用,会去执行log函数,由于该函数没有返回值,log(apple)返回为None,也就是appple = None, 再次执行appple()则会报错。
为了解决这个问题,正确的写法应该是在log中返回一个函数,而不是去执行该函数。
1 2 3 4 5 6 7 8 9 10 def  apple ():    print ("there is an apple" ) def  log (func ):    print ("this is log" )     return  func apple = log(apple)  apple() 
 
假如apple函数需要传入参数 1 2 3 4 5 6 7 8 9 10 11 12 def  apple (count ):    if  count == 1 :         print ("there is an apple" )     elif  count > 1 :         print (f"there are {count}  apples" ) def  log (func ):    print ("this is log" )     return  func apple = log(apple(count))  apple() 
 
按照之前的逻辑,直接像上面这样写肯定不行,因为apple(count)会直接执行该函数,那么log(apple(count))中log函数的参数便不再是函数了,而是apple(count)的结果。
同样的逻辑,需要将保证apple为一个函数,且需要能接受参数,则在原来的log里面先定义一个能接受任意参数的help函数,将它返回。
help函数里面应该写什么呢?
首先它需要记录log,并且根据传入的参数直接将其作为func函数的参数,并返回。当然在这个例子中,这里不返回直接执行也是可以的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def  apple (count ):    if  count == 1 :         print ("there is an apple" )     elif  count > 1 :         print (f"there are {count}  apples" ) def  log (func ):    def  help (*arg, **args ):         print ("this is log" )         return  func(*arg, **args)              return  help  apple = log(apple)  apple(5 ) 
 
装饰器 为了简化apple = log(apple)这个操作,python给出了一个简单的语法规则“@”将该步骤自动化,也就是“装饰器”。 
注意这里装饰器需要先定义再使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def  log (func ):    def  help (*arg, **args ):         print ("this is log" )         return  func(*arg, **args)     return  help  @log def  apple (count ):    if  count == 1 :         print ("there is an apple" )     elif  count > 1 :         print (f"there are {count}  apples" ) apple(5 ) 
 
装饰器参数 如果装饰器也需要添加参数怎么办呢。那么在外层再封装一层函数即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def  log (level ):  def  log_decorator (func ):     def  help (*arg, **args ):         print (f"Logging level: {level} " )         print ("this is log" )         return  func(*arg, **args)     return  help    return  log_decorator      @log("info"  ) def  apple (count ):    if  count == 1 :         print ("there is an apple" )     elif  count > 1 :         print (f"there are {count}  apples" )     apple(5 ) 
 
类装饰器 python基础 
:::success 类装饰器本质是通过类的魔术方法__call__来实现上述函数装饰器的类似功能,但使用类装饰器最大的好处是可以保存实例对象(注意不是类)的历史数据。
:::
类装饰器 :类装饰器通过定义一个类来实现装饰器功能。通常需要实现 __init__ 和 __call__ 方法:
__init__:初始化装饰器,接收被装饰的函数作为参数。 
__call__:使类的实例可以像函数一样被调用,从而实现对目标函数的包装。 
 
 
 
类装饰器的基本语法 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class  Decorator :    def  __init__ (self, func ):         self.func = func       def  __call__ (self, *args, **kwargs ):                  print ("Before function call" )         result = self.func(*args, **kwargs)         print ("After function call" )         return  result @Decorator def  my_function ():    print ("Function executed" ) my_function() 
 
输出: 
1 2 3 Before function call Function executed After function call 
 
类装饰器的工作原理 
装饰器的执行时机 :
当使用 @Decorator 装饰函数时,Python 会将被装饰的函数传递给装饰器类的构造函数(__init__)。 
被装饰的函数会被保存为类的实例属性(如 self.func)。 
 
 
调用被装饰的函数 :
当调用被装饰的函数时,实际上是调用了装饰器类的 __call__ 方法。 
在 __call__ 方法中,可以执行额外的逻辑,然后调用原始函数。 
 
 
 
类装饰器的应用场景 
类装饰器适用于以下场景:
需要维护状态的装饰器 : 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class  CountCalls :    def  __init__ (self, func ):         self.func = func         self.call_count = 0        def  __call__ (self, *args, **kwargs ):         self.call_count += 1          print (f"Call count: {self.call_count} " )         return  self.func(*args, **kwargs) @CountCalls def  say_hello ():    print ("Hello!" ) say_hello()   say_hello()   
 
- 类装饰器可以通过实例属性存储状态,而函数装饰器通常需要通过闭包实现类似功能。
 
复杂的装饰逻辑 : 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class  LoggingDecorator :    def  __init__ (self, func ):         self.func = func     def  log (self, message ):         print (f"[LOG] {message} " )     def  __call__ (self, *args, **kwargs ):         self.log("Before function call" )         result = self.func(*args, **kwargs)         self.log("After function call" )         return  result @LoggingDecorator def  add (a, b ):    return  a + b print (add(3 , 5 ))  
 
- 如果装饰器需要处理复杂的逻辑,类装饰器可以通过方法分解逻辑,使代码更清晰。
 
参数化的装饰器 : 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class  Repeat :    def  __init__ (self, times ):         self.times = times       def  __call__ (self, func ):         def  wrapper (*args, **kwargs ):             for  _ in  range (self.times):                 func(*args, **kwargs)         return  wrapper @Repeat(times=3  ) def  greet (name ):    print (f"Hello, {name} !" ) greet("Alice" ) 
 
和函数的过程类似。需要再外面再封装一层。实现过程为
实例化类对象,传入times参数为3 
调用__call__方法,传入func函数 
 
 
类装饰器与函数装饰器的对比 
特性  
类装饰器  
函数装饰器  
 
 
实现方式  
使用类和 __call__ 方法 
使用嵌套函数 
 
状态管理  
可以通过实例属性轻松管理状态 
需要通过闭包管理状态 
 
复杂逻辑分解  
可以通过类的方法分解复杂逻辑 
所有逻辑通常集中在一个函数中 
 
适用场景  
需要维护状态或逻辑较复杂的装饰器 
简单装饰器 
 
 
注意事项 
确保实现 __call__  方法 :
类装饰器必须实现 __call__ 方法,否则无法像函数一样调用。 
 
 
避免不必要的实例化 :
如果装饰器不需要维护状态,函数装饰器可能更简单高效。 
 
 
兼容性 :
类装饰器和函数装饰器在功能上是等价的,选择哪种方式取决于具体需求。 
 
 
 
//