为什么”来福“的位置不太对?
class MethodType:def __init__(self, func, object):
self.__func__ = func
self.__self__ = obj
def __call__(self, *args, **kwargs):
func = self.__func__
obj = self.__self__
print("小白")
return func(obj, *args, **kwargs)
class ClassMethod:
def __init__(self,f):
self.f = f
def __get__(self, obj, cls=None):
if cls is None:
print("旺财")
cls = type(obj)
if hasattr(type(self.f),'__get__'):
print(f"来福, type(self.f)->{type(self.f)}")
return self.f.__get__(cls,cls)
return MethodType(self.f, cls)
class D:
@ClassMethod
@property
def __doc__(cls):
return f"I love FishC. -- from class {cls.__name__}"
跟着小甲鱼的视频里面敲的,为什么我在实例化的时候,就会打印”来福“那一段文字呢?视频里是访问__doc__的时候才会打印的才对呀~ 首先,让我们来解释一下代码中的几个关键点。
1. `@ClassMethod`装饰器:这是一个自定义的装饰器,用于修饰类方法。在本例中,它被用于修饰属性方法`__doc__`。
2. `ClassMethod`类:这个类是为了模拟类方法的特性而创建的。它实现了`__get__`方法,当我们通过实例去访问属性时会被调用。
3. `MethodType`类:这个类用于将函数与对象绑定在一起,并返回一个可调用的对象。
现在让我们来看看代码中`ClassMethod`的使用:
class D:
@ClassMethod
@property
def __doc__(cls):
return f"I love FishC. -- from class {cls.__name__}"
在这里,我们将`ClassMethod`装饰器应用到`__doc__`属性上。当我们通过实例去访问`__doc__`属性时,`__get__`方法会被调用,并且会打印出"来福, type(self.f)->{type(self.f)}"。
这是因为在`__get__`方法中,我们首先检查`cls`是否为None。在这种情况下,我们使用`type(obj)`来获取`obj`的类。而在我们实例化`D`类的时候,`obj`是None,所以会打印出"来福"这段文字。
如果你想避免打印"来福"这段文字,可以修改`__get__`方法中的代码如下:
def __get__(self, obj, cls=None):
if cls is None and obj is not None:
cls = type(obj)
if hasattr(type(self.f),'__get__'):
return self.f.__get__(cls,cls)
return MethodType(self.f, cls)
这样修改后,只有在访问`__doc__`属性时才会打印出"I love FishC. -- from class D",而不会打印"来福"。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 在你提供的代码中,出现了一个小错误,这可能是造成你观察到的行为与预期不符的原因。在 MethodType 类的 __init__ 方法中,你初始化了 self.__self__ = obj,但是参数名是 object,不是 obj。这应该更正为 self.__self__ = object。然而,这个错误并不直接影响到“来福”那段文字的打印问题。
原因在于,你的 ClassMethod 类装饰器在被应用到通过 @property 装饰的 __doc__ 属性时,已经触发了其 __get__ 方法的调用。具体来说,当Python解释器加载你的类定义时,它会处理 @ClassMethod 和 @property 装饰器。由于 @ClassMethod 装饰器被设计为在属性访问时介入,其 __get__ 方法会在尝试获取 __doc__ 属性的描述符时被调用。
这里的关键在于,@property 本身创建了一个描述符,@ClassMethod 装饰器进一步包装了这个描述符。当Python试图解析这个被双重装饰的 __doc__ 属性时,它会调用 ClassMethod 的 __get__ 方法来获取最终的可调用对象。这一过程发生在类的定义阶段,而不是在属性访问时,因为 @property 已经将 __doc__ 方法包装为一个属性访问的描述符,然后 @ClassMethod 再次包装这个描述符,这就导致了 __get__ 方法的立即调用。
这个过程中,当 __get__ 方法检查 self.f(实际上是通过 @property 装饰的 __doc__ 方法)时,由于它发现这个对象有自己的 __get__ 方法(@property 创建的描述符具有 __get__ 方法),它打印出了“来福”并返回了 self.f.__get__(cls,cls),这就是为什么你在实例化类 D 时就看到了那段文字。这种行为与预期不符,因为装饰器的组合使用方式导致了一些意外的早期调用行为。
要解决这个问题,你可能需要重新考虑你的装饰器设计,或者避免将 @ClassMethod 和 @property 一起使用在同一个方法上。如果你的目的是创建一个可以作为类方法访问的属性,可能需要一个更简单的实现策略。
求最佳答案
页:
[1]