第77讲里的问题
之前课程里有讲过装饰器的联用,我将@property变成了下面的形式,为啥会报错呢?有没有什么好的解决办法呢?class D:
@classmethod
def __doc__(cls):
return f"hi,this is{cls.__name__}"
__doc__ = property(__doc__)
d = D()
d.__doc__
Traceback (most recent call last):
File "<pyshell#69>", line 1, in <module>
d.__doc__
TypeError: 'classmethod' object is not callable 本帖最后由 isdkz 于 2023-2-22 06:01 编辑
classmethod是为了让property对象去调用相应的方法的时候可以自动传入 cls 参数
这里出错是因为你先把 __doc__ 装饰成了 classmethod 对象,classmethod 对象是不能被直接调用的,它只能通过类和对象来去调用,
所以 property对象 去自动调用一个已经被装饰成 classmethod 对象的方法的时候就会报 classmethod' object is not callable 的错误,
所以不能在 property 之前把方法装饰成 classmethod 对象,都使用装饰器的时候是这样的:
@classmethod
@property
def __doc__
越靠近函数的装饰器是先装饰的,如果 property 使用函数的话,classmethod 就不能使用装饰器了,
因为装饰器只能在函数定义的时候使用,如果 classmethod 得在 property 之后的话也得使用函数
故对你的代码修改如下:
class D:
def __doc__(cls):
return f"hi,this is {cls.__name__}"
__doc__ = classmethod(property(__doc__))
d = D()
print(d.__doc__) 在这个例子中,你使用了一个装饰器来将一个类方法转换为一个属性,即将类方法 __doc__ 转换为属性。然而,这个装饰器并不适用于类方法。当你试图获取属性 __doc__ 的值时,Python 尝试调用类方法 __doc__,但由于这个类方法现在已经变成了属性,所以会引发一个 TypeError 异常。
要解决这个问题,你可以使用另一种方法来将类方法转换为属性。一个常用的方法是使用 @property 装饰器来创建一个属性,然后使用 @类方法名.setter 装饰器来定义一个与属性对应的 setter 方法。下面是一个修改后的示例代码:class D:
@classmethod
def __doc__(cls):
return f"hi,this is{cls.__name__}"
@property
def doc(self):
return self.__doc__
@doc.setter
def doc(self, value):
self.__doc__ = value
d = D()
print(d.doc) # 输出 "hi,this isD"
在这个代码中,我们使用 @property 装饰器来定义一个属性 doc,并且使用 @doc.setter 装饰器来定义一个与 doc 属性对应的 setter 方法。这样,我们就可以将类方法 __doc__ 转换为一个属性,并且可以通过 d.doc 来获取和设置其值。 谢谢各位大神了
页:
[1]