如何让@property数据描述符的类型提示在help文档中显示?
先看示例代码:
class Book: def __init__(self, title, author): self._title = title self._author = author @property def title(self) -> str: """Retrieve the book's title""" return self._title def author(self) -> str: """Retrieve the book's author""" return self._author
调用help(Book)后,得到的简化文档是:
class Book(builtins.object) | Methods defined here: | | author(self) -> str | Retrieve the book's author | | ---------------------------------------------------------------------- | Data descriptors defined here: | | title | Retrieve the book's title
可以看到普通方法author的类型提示-> str正常显示,但作为@property的数据描述符title,它的返回类型提示却没出现在help()输出里。除了把类型写进文档字符串(容易导致代码和文档不一致),有没有其他办法让@property的类型提示在help()中显示?
这个问题我之前也折腾过,确实Python默认的help()对@property的类型提示支持有点滞后,不过有几个不用硬写在文档里的可行方案:
1. 类级别的属性类型注解
最简单的方法就是在类里直接给title加个类级别的类型注解,help()会自动识别并显示这个类型:
class Book: title: str # 这里添加类级别的属性类型注解 _title: str _author: str def __init__(self, title: str, author: str): self._title = title self._author = author @property def title(self) -> str: """Retrieve the book's title""" return self._title def author(self) -> str: """Retrieve the book's author""" return self._author
这时再调用help(Book),title的描述会变成:
title Retrieve the book's title Type: str
这个方法最省心,不用改装饰器或者额外代码,而且类型注解和业务代码分离,不容易出错。
2. 自定义带类型识别的Property装饰器
如果想要让@property的显示风格和普通方法更接近(比如显示返回类型提示),可以自己写个自定义的TypedProperty装饰器,自动从getter函数的注解里提取返回类型,整合到文档中:
class TypedProperty(property): def __init__(self, fget=None, fset=None, fdel=None, doc=None): super().__init__(fget, fset, fdel, doc) # 从getter函数中读取返回类型注解 if fget and 'return' in fget.__annotations__: self.return_type = fget.__annotations__['return'] # 给文档字符串追加类型提示,不会修改原函数的docstring if self.__doc__: self.__doc__ = f"{self.__doc__}\n Returns: {self.return_type.__name__}" # 使用自定义装饰器替代@property class Book: def __init__(self, title: str, author: str): self._title = title self._author = author @TypedProperty def title(self) -> str: """Retrieve the book's title""" return self._title def author(self) -> str: """Retrieve the book's author""" return self._author
调用help(Book)后,title的描述会变成:
title Retrieve the book's title Returns: str
这种方式可以让属性的文档和方法的文档风格更统一,而且类型提示完全来自代码的注解,不会出现不一致的问题。
3. 手动给@property对象添加注解
还有个更直接的办法,就是手动给title这个property对象添加__annotations__属性,让help()能识别到它的返回类型:
class Book: def __init__(self, title: str, author: str): self._title = title self._author = author @property def title(self) -> str: """Retrieve the book's title""" return self._title # 手动给property对象添加返回类型注解 title.__annotations__ = {'return': str} def author(self) -> str: """Retrieve the book's author""" return self._author
不过这个方法在部分Python版本中,help()可能不会主动展示这个注解,建议搭配类级别的注解一起使用,效果会更稳定。
内容的提问来源于stack exchange,提问作者AJNeufeld

