Python中关于类装饰器的使用问题请教
1、下面是第一个类装饰器
def decorator(cls):
class Wrapper:
def __init__(self, *args):
self.wrapped = cls(*args)
def __getattr__(self, name):
return getattr(self.wrapped, name)
return Wrapper
[@decorator](/user/decorator)
class C:
def __init__(self, x, y):
self.attr = 'spam'
2、下面是第二个类装饰器
class Decorator:
def __init__(self, C):
self.C = C
def __call__(self, *args):
self.wrapped = self.C(*args)
return self
def __getattr__(self, attrname):
return getattr(self.wrapped, attrname)
[@Decorator](/user/Decorator)
class C: ...
我看到书上说,第二个类装饰器和第一个不同,第二个没有能够处理给定的类的多个实例——每个实例创建调用都覆盖了前面保存的实例。第一个类装饰器却支持多个实例,因为每个实例创建调用产生了一个新的独立的包装器对象。
请问怎么理解上面这段话,为何第二个类装饰器在每个实例创建时都会覆盖前面保存的实例呢? 感谢指点!
Python中关于类装饰器的使用问题请教
去看描述器 看完再回来看你的问题
在Python里,类装饰器本质上是一个可调用对象(通常是函数或类),它接收一个类作为参数,并返回一个修改后的类(或一个完全不同的类)。最常见的用法是用一个函数包裹目标类,在函数内部修改或增强类的行为,然后返回这个类。
一个最直接的模式是写一个接收cls参数的函数,在函数内部动态修改类(比如添加、修改方法或属性),最后返回修改后的类。下面是一个给类添加新方法的完整例子:
def add_method_to_class(cls):
"""类装饰器:给类动态添加一个实例方法"""
def new_method(self):
return f"{self.__class__.__name__} called new_method"
# 将新方法绑定到类上
cls.new_method = new_method
return cls
@add_method_to_class
class MyClass:
def original_method(self):
return "original"
obj = MyClass()
print(obj.original_method()) # 输出: original
print(obj.new_method()) # 输出: MyClass called new_method
更复杂一点,你可以用类来实现装饰器。这种类需要实现__init__和__call__方法,__init__接收被装饰的类,__call__在类被实例化时介入。下面是一个用类实现的装饰器,它拦截实例创建并打印日志:
class LogInstances:
"""类装饰器(用类实现):记录类的实例化"""
def __init__(self, cls):
self.cls = cls
self.instance_count = 0
def __call__(self, *args, **kwargs):
self.instance_count += 1
print(f"Creating instance {self.instance_count} of {self.cls.__name__}")
return self.cls(*args, **kwargs)
@LogInstances
class MyClass:
pass
obj1 = MyClass() # 输出: Creating instance 1 of MyClass
obj2 = MyClass() # 输出: Creating instance 2 of MyClass
类装饰器的一个强大用途是自动注册子类。比如在Web框架中,常用类装饰器将视图类注册到路由系统:
_registry = []
def register_view(cls):
"""类装饰器:自动注册视图类"""
_registry.append(cls)
return cls
@register_view
class HomeView:
pass
@register_view
class UserView:
pass
print(_registry) # 输出: [<class '__main__.HomeView'>, <class '__main__.UserView'>]
核心要点: 类装饰器就是修改或包装类的函数或类。
哦理解错,我以为是类里面的装饰器 ,你这是装饰类的装饰器
这不很简单么第二个类装饰器可以预接参数成为实例,然后装饰类的时候是这个实例的 call 方法去套
第一个是相当于把这个装饰器类实例化,初始化参数就是一个类
装饰器就是套娃语法糖 func(func(func()))
自己套一下就知道了
谢谢,你写得话我基本能看明白,但是我还是无法和我的问题联系起来理解,第二个类装饰器是调用 Decorator.__call__方法,可这和“没有能够处理给定的类的多个实例——每个实例创建调用都覆盖了前面保存的实例”这句话有什么关系?
我不知道要怎么理解这句话“没有能够处理给定的类的多个实例——每个实例创建调用都覆盖了前面保存的实例。” ,覆盖?怎么个覆盖法?
因为只是在调用一个 global 的 functor instance (
您是说 self.C 是从外部传入的参数,所以可以看做是 global 的实例化方法,但是 cls 就是作用域在 wrapper 定义域内的实例化方法么?
关于这个问题,我另外又发了个帖子,我觉得好像找到了存在矛盾的例子,能否指点,感谢!
https://www.v2ex.com/t/384994#reply0

