鱼C论坛

 找回密码
 立即注册
查看: 2382|回复: 3

[已解决]第77讲里的问题

[复制链接]
发表于 2023-2-22 01:09:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
之前课程里有讲过装饰器的联用,我将@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
最佳答案
2023-2-22 05:58:18
本帖最后由 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__)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-2-22 05:58:18 | 显示全部楼层    本楼为最佳答案   
本帖最后由 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__)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-2-22 08:39:35 | 显示全部楼层
在这个例子中,你使用了一个装饰器来将一个类方法转换为一个属性,即将类方法 __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 来获取和设置其值。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 0 反对 1

使用道具 举报

 楼主| 发表于 2023-2-22 10:45:54 | 显示全部楼层
谢谢各位大神了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-24 13:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表