是否可以对普通变量使用docstring?例如,我有一个名为t的模块
def f():
"""f"""
l = lambda x: x
"""l"""我就是这么做的
>>> import t
>>> t.f.__doc__
'f'但
>>> t.l.__doc__
>>> 示例类似于PEP 258的示例(搜索"this is g")。
发布于 2012-01-11 22:07:22
使用typing.Annotated为变量提供文档字符串。
我最初写了一个答案(见下文),其中我说这是不可能的。这在2012年是正确的,但Python已经向前发展了。现在,您可以为全局变量或类或实例的属性提供等效的docstring。您需要至少运行Python 3.9才能正常工作:
from __future__ import annotations
from typing import Annotated
Feet = Annotated[float, "feet"]
Seconds = Annotated[float, "seconds"]
MilesPerHour = Annotated[float, "miles per hour"]
day: Seconds = 86400
legal_limit: Annotated[MilesPerHour, "UK national limit for single carriageway"] = 60
current_speed: MilesPerHour
def speed(distance: Feet, time: Seconds) -> MilesPerHour:
"""Calculate speed as distance over time"""
fps2mph = 3600 / 5280 # Feet per second to miles per hour
return distance / time * fps2mph您可以在运行时使用typing.get_type_hints()访问注释
Python 3.9.1 (default, Jan 19 2021, 09:36:39)
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import calc
>>> from typing import get_type_hints
>>> hints = get_type_hints(calc, include_extras=True)
>>> hints
{'day': typing.Annotated[float, 'seconds'], 'legal_limit': typing.Annotated[float, 'miles per hour', 'UK national limit for single carriageway'], 'current_speed': typing.Annotated[float, 'miles per hour']}使用声明变量的模块或类的提示提取有关变量的信息。请注意,当您嵌套注释时,它们是如何组合的:
>>> hints['legal_limit'].__metadata__
('miles per hour', 'UK national limit for single carriageway')
>>> hints['day']
typing.Annotated[float, 'seconds']它甚至适用于具有类型注释但尚未赋值的变量。如果我试图引用calc.current_speed,我会得到一个属性错误,但我仍然可以访问它的元数据:
>>> hints['current_speed'].__metadata__
('miles per hour',)模块的类型提示仅包括全局变量,要向下钻取,您需要在函数或类上再次调用get_type_hints():
>>> get_type_hints(calc.speed, include_extras=True)
{'distance': typing.Annotated[float, 'feet'], 'time': typing.Annotated[float, 'seconds'], 'return': typing.Annotated[float, 'miles per hour']}到目前为止,我只知道一种工具可以使用typing.Annotated来存储有关变量的文档,那就是Pydantic。它比仅仅存储文档字符串稍微复杂一些,尽管它实际上需要一个pydantic.Field的实例。下面是一个例子:
from typing import Annotated
import typing_extensions
from pydantic import Field
from pydantic.main import BaseModel
from datetime import date
# TypeAlias is in typing_extensions for Python 3.9:
FirstName: typing_extensions.TypeAlias = Annotated[str, Field(
description="The subject's first name", example="Linus"
)]
class Subject(BaseModel):
# Using an annotated type defined elsewhere:
first_name: FirstName = ""
# Documenting a field inline:
last_name: Annotated[str, Field(
description="The subject's last name", example="Torvalds"
)] = ""
# Traditional method without using Annotated
# Field needs an extra argument for the default value
date_of_birth: date = Field(
...,
description="The subject's date of birth",
example="1969-12-28",
)使用模型类:
>>> guido = Subject(first_name='Guido', last_name='van Rossum', date_of_birth=date(1956, 1, 31))
>>> print(guido)
first_name='Guido' last_name='van Rossum' date_of_birth=datetime.date(1956, 1, 31)Pydantic模型可以为您提供JSON模式:
>>> from pprint import pprint
>>> pprint(Subject.schema())
{'properties': {'date_of_birth': {'description': "The subject's date of birth",
'example': '1969-12-28',
'format': 'date',
'title': 'Date Of Birth',
'type': 'string'},
'first_name': {'default': '',
'description': "The subject's first name",
'example': 'Linus',
'title': 'First Name',
'type': 'string'},
'last_name': {'default': '',
'description': "The subject's last name",
'example': 'Torvalds',
'title': 'Last Name',
'type': 'string'}},
'required': ['date_of_birth'],
'title': 'Subject',
'type': 'object'}
>>> 如果您在FastAPI应用程序中使用这个类,那么OpenApi规范中有取自相关字段的所有这三个类的示例和描述。
这是最初的答案,当时是正确的,但没有经受住时间的考验:
不,这是不可能的,即使你可以,它也不会有什么用处。
文档字符串始终是对象(模块、类或函数)的属性,而不是绑定到特定变量。
这意味着如果你可以这样做:
t = 42
t.__doc__ = "something" # this raises AttributeError: '__doc__' is read-only您将为整数42设置文档,而不是为变量t设置。一旦重新绑定t,就会丢失文档字符串。不可变对象(例如许多字符串)有时会在不同用户之间共享一个对象,因此在本例中,您可能实际上已经为整个程序中出现的所有42设置了文档字符串。
print(42 .__doc__) # would print "something" if the above worked!对于可变对象,它不一定是有害的,但如果您重新绑定对象,它的使用仍然是有限的。
如果你想记录一个类的属性,那么使用类的文档字符串来描述它。
发布于 2013-12-12 04:56:07
Epydoc支持docstrings on variables
虽然语言没有直接提供它们,但Epydoc支持变量文档字符串:如果变量赋值语句后面紧跟一个纯字符串文字,那么该赋值将被视为该变量的文档字符串。
示例:
class A:
x = 22
"""Docstring for class variable A.x"""
def __init__(self, a):
self.y = a
"""Docstring for instance variable A.y"""发布于 2015-08-02 01:34:58
好吧,尽管Python不会将在全局定义之后立即定义的字符串视为变量的文档字符串,但sphinx会这样做,并且将它们包含进来肯定不是一种坏的做法。
debug = False
'''Set to True to turn on debugging mode. This enables opening IPython on
exceptions.
'''下面是一些代码,它将扫描模块并提取全局变量定义的名称、值和随后的文档字符串。
def GetVarDocs(fname):
'''Read the module referenced in fname (often <module>.__file__) and return a
dict with global variables, their value and the "docstring" that follows
the definition of the variable
'''
import ast,os
fname = os.path.splitext(fname)[0]+'.py' # convert .pyc to .py
with open(fname, 'r') as f:
fstr = f.read()
d = {}
key = None
for node in ast.walk(ast.parse(fstr)):
if isinstance(node,ast.Assign):
key = node.targets[0].id
d[key] = [node.value.id,'']
continue
elif isinstance(node,ast.Expr) and key:
d[key][1] = node.value.s.strip()
key = None
return dhttps://stackoverflow.com/questions/8820276
复制相似问题