Python 3.12 Special Attribute - 04 - __doc__

张开发
2026/6/7 14:06:30 15 分钟阅读
Python 3.12 Special Attribute - 04 - __doc__
Python 3.12 Special Attribute -__doc____doc__是 Python 中用于存储对象文档字符串docstring的内置特殊属性。文档字符串是写在模块、类、函数或方法定义首部的一个字符串字面量用于描述该对象的功能和使用方法。__doc__属性使得这些文档可以在运行时被访问便于交互式帮助、自动生成文档以及代码自省。正确使用文档字符串是编写可维护、可读性强的 Python 代码的最佳实践之一。本文将详细解析__doc__的定义、用途、在不同对象上的表现、底层实现并通过多个示例演示如何编写和访问文档字符串。1.__doc__的基本概念定义__doc__是一个字符串或None存储对象的文档字符串。位置出现在模块、类、函数、方法定义后的第一个语句如果该语句是一个字符串字面量可以跨行则被 Python 解释器自动绑定到对象的__doc__属性。特点文档字符串不会被解释器执行仅用于文档目的。可以通过help(obj)或obj.__doc__访问。注意如果对象没有文档字符串则__doc__为None。多个字符串如果连续出现只有第一个被视为文档字符串。2. 用途与典型场景提供使用说明在交互式环境中使用help(obj)可以显示对象的文档字符串。自动生成文档工具如 Sphinx、pydoc 可以提取__doc__生成 API 文档。代码自省在运行时获取对象的描述信息用于调试或动态行为。规范编程遵循 PEP 257文档字符串约定可以提高代码可读性和团队协作效率。文档字符串通常包含简要描述参数说明对于函数/方法返回值说明可能引发的异常使用示例3. 不同对象上的__doc__3.1 模块的__doc__模块的文档字符串应放在模块文件的顶部位于任何导入语句或代码之前。# module_demo.pyThis is a module for demonstrating __doc__. It contains a function and a class. defadd(a,b):Return the sum of a and b.returnabclassCalculator:A simple calculator class.pass访问模块的__doc__importmodule_demoprint(module_demo.__doc__)# 输出: This is a module for demonstrating __doc__.# It contains a function and a class.3.2 类的__doc__类的文档字符串应紧跟在类定义行之后。classCar:Represents a car with make, model, and year.def__init__(self,make,model,year):self.makemake self.modelmodel self.yearyear访问print(Car.__doc__)# Represents a car with make, model, and year.3.3 函数/方法的__doc__函数的文档字符串应紧跟在函数定义行之后。defmultiply(x,y):Multiply two numbers and return the product.returnx*y访问print(multiply.__doc__)# Multiply two numbers and return the product.对于方法同样适用。4. 示例与逐行解析示例 1多行文档字符串defcomplex_function(a,b,c0): Compute something complex. Parameters: a (int): First argument. b (int): Second argument. c (int, optional): Third argument, default 0. Returns: int: The computed result. returnabcprint(complex_function.__doc__)逐行解析行代码解释1定义函数包含参数a,b,c。2-8多行字符串使用三重引号这是文档字符串包含参数和返回值描述。9函数体实际逻辑。11访问__doc__打印文档字符串内容。为什么这样写使用三重双引号可以编写多行文档保持格式清晰。遵循 PEP 257 推荐的风格第一行简要描述空一行然后详细说明。示例 2继承与文档字符串子类不会自动继承父类的文档字符串但可以通过super().__doc__访问父类的文档。classParent:Parent class docstring.passclassChild(Parent):Child class docstring.passprint(Parent.__doc__)# Parent class docstring.print(Child.__doc__)# Child class docstring.print(Child.__bases__[0].__doc__)# Parent class docstring.逐行解析子类可以拥有自己的文档字符串覆盖父类的。父类的文档仍可通过父类本身访问。示例 3动态修改__doc__文档字符串是可写的可以在运行时修改。deffunc():passprint(func.__doc__)# Nonefunc.__doc__Dynamically added docstring.print(func.__doc__)# Dynamically added docstring.注意动态修改文档字符串通常不推荐因为它可能使自动生成的文档与实际代码不一致。示例 4使用help()显示文档defadd(a,b):Return a b.returnabhelp(add)# 在交互式环境中会显示函数的文档字符串5. 底层实现机制在 CPython 中__doc__属性的存储依赖于对象的类型对于函数/方法__doc__存储在函数对象的func_doc字段中C 结构体PyFunctionObject的成员。当解析器遇到一个函数定义后的字符串字面量时它会将该字符串作为__doc__存储。对于类类的__doc__是类字典中的一项。在构建类时如果类体中的第一个语句是字符串字面量它会被提取并设置到__doc__属性中。对于模块模块的__doc__也是模块__dict__中的一项在模块编译时从模块文件的起始字符串字面量提取。编译过程当 Python 编译源代码时AST 构建阶段会识别文档字符串并生成相应的LOAD_CONST和STORE_ATTR字节码将字符串赋值给对象的__doc__属性。例如deff():docpass生成的字节码中会有0 LOAD_CONST 1 (code object f) 2 LOAD_CONST 2 (f) 4 MAKE_FUNCTION 0 6 STORE_NAME 0 (f) 8 LOAD_CONST 3 (doc) 10 LOAD_CONST 0 (None) 12 STORE_ATTR 1 (__doc__) 14 ...实际上__doc__的赋值是在函数对象创建后立即进行的因此文档字符串在定义时就已经绑定。6. 文档字符串的约定PEP 257第一行应为简短描述以句号结尾。多行文档第一行后空一行然后写详细描述。使用三重双引号。对于类在__init__方法的文档中描述构造函数参数。对于包在__init__.py文件中添加模块级文档字符串。示例defcomplex_function(a,b): Compute the sum of a and b. This is a longer description that can span multiple lines. It can include examples: complex_function(2, 3) 5 returnab7. 注意事项与陷阱文档字符串必须是字符串字面量不能是变量或表达式结果。例如__doc__ Hello不是文档字符串而是普通属性赋值。继承子类不会自动继承父类的文档字符串需要显式复制或使用装饰器。动态修改的风险修改__doc__可能使help()显示过时信息应谨慎。__doc__与inspect.getdoc()inspect.getdoc(obj)会清理缩进并可能查找继承链中的文档比直接访问__doc__更友好。对于lambda函数由于lambda体只能是表达式不能包含文档字符串因此其__doc__总是None。8. 总结特性说明角色存储对象的文档字符串提供可读的描述信息类型str或None位置模块、类、函数、方法定义后的第一个字符串字面量访问方式obj.__doc__或help(obj)可写性可读可写但动态修改不推荐底层CPython 在编译时提取字符串并存储到对象特定字段典型用途交互式帮助、文档生成、代码自省最佳实践遵循 PEP 257使用三重双引号提供清晰描述掌握__doc__是编写专业 Python 代码的基础。良好的文档字符串不仅能帮助他人理解你的代码也能在数月后提醒你自己。结合help()和自动文档工具__doc__是 Python 生态中知识传递的重要桥梁。如果在学习过程中遇到问题欢迎在评论区留言讨论!

更多文章