首页 > 解决方案 > 如何在 Python 3.9 / 3.10 中记录类方法属性?

问题描述

python 3.9 的一个小插件是

在 3.9 版更改:类方法现在可以包装其他描述符,例如 property()。

这在几种情况下很有用,例如作为在类方法上使用 property()的解决方案,或者为了通过配方创建本质上是一个懒惰评估的类属性

class A:
   @classmethod
   @property
   @cache
   def lazy_class_attribute(cls):
       """Method docstring."""
       return expensive_computation(cls)

这在python中运行良好,导入类,实例化它或它的子类不会导致expensive_computation发生,但是似乎两者pydoc并且sphinx不仅会expensive_computation在他们尝试获取文档字符串时导致执行,而且不会为此显示任何文档字符串@classmethod任何。

问题:是否有可能 - 从 python (*) 中 - 懒惰地评估在构建文档时未执行的类属性/属性?

(*)停止 Sphinx 执行缓存的类方法属性中提出的一种解决方法,感谢 /u/jsbueno,包括根据环境变量修改函数体:

def lazy_class_attribute(cls):
   """Method docstring."""
    if os.environ.get("GENERATING_DOCS", False):
        return
   return expensive_computation(cls)

我非常喜欢这种解决方法,因为特别是,它允许人们在记录时呈现不同的输出。(例如,我的类具有基于类名的路径属性。如果不同的用户执行相同的脚本,则路径将不同,因为它们的主文件夹不同。)

但是有两个问题:

  1. 这种方法取决于在 python 之外做的事情,imo,在理想的世界中,没有必要在 python 本身之外做
  2. 为了在文档中获取文档字符串,似乎我们最终不得不做一些不直观的事情,比如
class MetaClass:
    @property
    @cache
    def _expensive_function(cls):
        """some expensive function"""

class BaseClass(metaclass=MetaClass):
    lazy_attribute: type = classmethod(MetaClass._expensive_funcion)
    """lazy_attribute docstring"""

在此处输入图像描述

PS:顺便问一下, a@classmethod@property和 an之间有什么功能上的区别attribute吗?它们看起来非常相似。目前我能做出的唯一区别是,如果该属性需要访问其他@classmethods,我们需要像上面一样移动元类中的所有内容。

标签: docstringpython-3.9python-3.10

解决方案


推荐阅读