是否可以将文档字符串用于普通变量?例如,我有一个名为 t
def f():
"""f"""
l = lambda x: x
"""l"""
我愿意
>>> import t
>>> t.f.__doc__
'f'
但是
>>> t.l.__doc__
>>>
示例类似于 PEP 258 's(搜索“这是 g”)。
最佳答案
使用 typing.Annotated
为变量提供一个文档字符串。
我最初写了一个答案(见下文),我说这是不可能的。早在 2012 年就是如此,但 Python 继续前进。今天,您可以为全局变量或类或实例的属性提供等效的文档字符串。您至少需要运行 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
设置文档。一旦你重新绑定(bind) t
你就会丢失文档字符串。不可变对象(immutable对象)(例如字符串数)有时在不同用户之间共享一个对象,因此在此示例中,您实际上可能已经为整个程序中所有出现的 42
设置了文档字符串。
print(42 .__doc__) # would print "something" if the above worked!
对于可变对象,它不一定有害,但如果您重新绑定(bind)对象,它的用途仍然有限。
如果你想记录一个类的属性,那么使用类的文档字符串来描述它。
关于python - 变量的文档字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8820276/