Matplotlib 项目
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
本页面包含 Google 文档季接受的技术写作项目的详细信息。
项目摘要
- 开源组织:
- Matplotlib
- 技术文档工程师:
- brunobeltran
- 项目名称:
- 通过标准化“隐式”类型的文档来提高功能的可检测性
- 项目时长:
- 长期(5 个月)
Project description
设计初衷
过去,matplotlib 的 API 严重依赖于字符串即枚举“隐式类型”。除了模仿 matlab 的 API 之外,这些参数字符串还允许用户将富含语义的值作为参数传递给 matplotlib 函数,而无需仅为了传递基本绘图选项而明确导入或冗长地为实际枚举值添加前缀(即 plt.plot(x, y, linestyle='solid')
比 plt.plot(x, y,
linestyle=mpl.LineStyle.solid)
更易于输入且更少冗余)。
这些将字符串用作枚举的隐式类型中的许多类型后来都演变出了更复杂的功能。例如,linestyle
现在可以是字符串,也可以是序列的 2 元组,MarkerStyle 现在可以是字符串,也可以是 matplotlib.path.Path
。虽然许多隐式类型都存在这种情况,但 MarkerStyle(据我所知)是唯一已升级为适当 Python 类的类型。
由于这些隐式类型本身并不是类,因此 Matplotlib 过去不得不推出自己的解决方案来集中对这些隐式类型的文档和验证(例如,分别使用 docstring.interpd.update
文档字符串插值模式和 cbook._check_in_list
验证器模式),而不是使用 Python 类提供的标准工具链(例如,验证文档字符串和 __init__
模式)。
虽然这些解决方案对我们来说非常有效,但缺少用于记录每种隐式类型的明确位置意味着文档往往难以找到,在整个文档中重复使用包含允许值的大表格,并且通常文档中完全缺少隐式类型的范围的显式声明。以 plt.plot
文档为例:在“备注”中,对类似于 Matlab 的格式字符串样式设置方法的说明中提到了 linestyle
、color
和 markers
选项。传递这三个值的方式比提示的方法要多得多,但对于许多用户来说,这是他们了解这些选项可能值的唯一来源,直到他们偶然看到某个相关教程。其中包含一个 Line2D
属性表,目的是向读者显示可用于控制图表的选项。不过,虽然 linestyle
条目很好地链接到了 Line2D.set_linestyle
(需要点击两次),其中描述了可能的输入,但 color
和 markers
条目却没有。color
只是链接到 Line2D.set_color
,无法提供任何关于允许哪些类型的输入的直观信息。
有人可能会说,只需整理导致问题的个别 docstring 即可解决此问题,但遗憾的是,这个问题远比这更系统化。如果没有集中查找文档的位置,这只会导致我们越来越多地复制越来越详尽的文档,并在每次使用这些隐式类型的每个位置重复这些文档,这会让新手用户更难找到他们所需的参数。不过,当前的系统也不可持续,因为它迫使用户通过在我们的文档中以 Wiki 方式浏览或从 StackOverflow 示例中零散地学习,慢慢拼凑出对每个隐式类型的心理模型。
最终目标
理想情况下,提及任何隐式类型时,都应链接到单个页面,该页面会说明该类型可以采用的所有可能的值,并按照从最简单、最常见到最高级或深奥的顺序排列。这样一来,我们就可以使用顶级 API 文档中宝贵的视觉空间,以分块方式枚举特定参数的所有可能输入类型,而不是使用相同的空间来用简单的文字描述该参数要控制的绘图抽象。
再次使用 linestyle
示例,我们在 LineCollection
文档中需要的只是:
- 指向有关允许的输入的完整文档的链接(
Line2D.set_linestyle
和线条样式教程中的文档组合)。
- 用简单的文字说明该参数的用途。对于 matplotlib 高级用户,这从参数名称中就可以看出来,但对于新用户来说,情况并非如此。
在实际的 LineCollection
文档中,这将如下所示:python
""""""
linestyles: `LineStyle` or list thereof, default: :rc:`lines.linestyle` ('-')
A description of whether the stroke used to draw each line in the collection
is dashed, dotted or solid, or some combination thereof.
""""""
其中,Sphinx 会解析 LineStyle
类型引用,以指向一组权威且完整的文档,其中介绍了 Matplotlib 如何处理线条样式。
优势
这种方法的一些强大功能包括
- 以纯文本形式清晰显示每个功能的全部功能(无需点击)。
- 将默认选项设为可见(无需点击)。看到默认选项通常足以唤起回访用户的记忆。
- 提供“最常用”和“最简单”选项的完整说明,以便在浏览时(只需点击一下)即可轻松找到参数。
- 只需“向下滚动”即可查看更多高级选项(只需点击一下),从而轻松发现更强大的功能和输入法。
- 提供一种集中的策略,用于将顶级“API”文档与相关“教程”相关联。
- 避免 API 文档爆炸,即扫描每个参数的许多可能选项会导致单个文档注释难以使用。
与当前文档相比,这种方法的其他优势包括:
- 由于集中化的原因,文档不太可能过时。
- 规范了目前必须通过阅读代码学习的 matplotlib 的许多“隐式标准”(例如“边界”与“范围”是什么)。
- 该流程会突出显示 API 一致性问题,使之通过 GitHub 问题跟踪器更轻松地进行跟踪,从而帮助改进我们的 API。
- 由于需要解析的文本量大幅减少,文档构建时间缩短。
实现
上述改进需要两项主要工作,对于这方面的工作,一名专门的技术文档工程师将非常有用。第一种方法是为每种隐式类型创建一个集中式“教程”页面。这需要与核心开发者团队合作,确定一组具体的隐式类型,其文档对用户来说非常有用(通常是因为这些类型包含我们库的强大隐藏功能,而这些功能的文档目前只能在很难找到的入门教程中找到)。然后,我会针对每种隐式类型,将各种相关教程、API 文档和示例页面整合到一个权威文档来源中,该来源可链接到引用特定类型的任何位置。
完成给定隐式类型的集中式文档后,我们将开始第二项主要工作:将现有 API 文档替换为指向新文档的链接,以便使用 Python 的内置 help()
实用程序的用户和在线浏览我们文档的用户都能尽可能轻松地实际使用这些新文档。
虽然此处提议的文档的确切格式可能会随着此项目的推进而发生变化,但我与 Matplotlib 核心团队在每周的“开发者通话”期间合作,共同达成了共识,即此处提出的策略是开始记录这些“隐式类型”时最便捷、最实用且在技术上最易于处理的方法(提供了关于这些调用的说明)。在为每个隐式类型创建集中式文档的初始阶段,我将使用现有的“教程”基础架构,这样我就可以像这样轻松引用这些页面,而无需创建任何新的公共类(再次以 LineCollection
文档为例):
""""""
linestyles: LineStyle or list thereof, default: :rc:`lines.linestyle` ('-')
A description of whether the stroke used to draw each line in the collection
is dashed, dotted or solid, or some combination thereof. For a full
description of possible LineStyle's, see :doc:`tutorials/types/linestyle`.
""""""
今后,一旦核心开发者团队就将我们的新“类型”文档纳入真正的 Python 类的最佳长期策略达成共识(例如我在 Matplotlib 增强提案 30 中提出的),我们就可以轻松更改这些引用的拼写方式。
最后,我建议在此 Google 文档季期间记录的隐式类型的初步列表如下:
capstyle
joinstyle
bounds
extents
linestyle
colors
/lists of colors
colornorm/colormap
tick formatters
您可以在我们的 Discourse 论坛上找到本文档的最新版本。
如未另行说明,那么本页面中的内容已根据知识共享署名 4.0 许可获得了许可。有关详情,请参阅 Google 开发者网站政策。Java 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-07-25。
[null,null,["最后更新时间 (UTC):2025-07-25。"],[[["\u003cp\u003eThis project aims to improve Matplotlib's documentation by creating centralized pages for "implicit types" like linestyles, colors, and bounds, currently scattered and difficult to find.\u003c/p\u003e\n"],["\u003cp\u003eThe goal is to enhance feature discoverability, making it easier for users to understand the full range of options for customizing their plots.\u003c/p\u003e\n"],["\u003cp\u003eThis will be achieved by consolidating information from various sources into dedicated tutorial pages linked from relevant API documentation.\u003c/p\u003e\n"],["\u003cp\u003eBenefits include easier navigation, better understanding of defaults, faster doc build times, and a more consistent and up-to-date documentation system.\u003c/p\u003e\n"],["\u003cp\u003eThe project involves identifying key implicit types, creating centralized documentation for each, and updating existing API docs with links to these new resources.\u003c/p\u003e\n"]]],["The project aims to improve Matplotlib's documentation by centralizing information about \"implicit types,\" which are string-based parameters used in plotting functions. The key actions include: creating tutorial pages for each implicit type (e.g., `linestyle`, `colors`), synthesizing existing documentation into a single authoritative source, and replacing scattered API documentation with links to these centralized resources. This will make the documentation more accessible, reduce redundancy, highlight API inconsistencies, and improve discoverability of advanced features. The goal is to describe the type in a complete way.\n"],null,["# Matplotlib project\n\nThis page contains the details of a technical writing project accepted for\nGoogle Season of Docs.\n\n### Project summary\n\nOpen source organization:\n: Matplotlib\n\nTechnical writer:\n: brunobeltran\n\nProject name:\n: Improving feature discoverability by standardizing documentation of \"implicit\" types\n\nProject length:\n: Long running (5 months)\n\n### Project description\n\n#### Motivation\n\nHistorically, matplotlib's API has relied heavily on string-as-enum\n\"\"implicit types\"\". Besides mimicking matlab's API, these parameter-strings allow the\nuser to pass semantically-rich values as arguments to matplotlib functions\nwithout having to explicitly import or verbosely prefix an actual enum value\njust to pass basic plot options (i.e. `plt.plot(x, y, linestyle='solid')` is\neasier to type and less redundant than something like `plt.plot(x, y,\nlinestyle=mpl.LineStyle.solid)`).\n\nMany of these string-as-enum implicit types have since evolved more\nsophisticated features. For example, a `linestyle` can now be either a string\nor a 2-tuple of sequences, and a MarkerStyle can now be either a string or a\n`matplotlib.path.Path`. While this is true of many implicit types, MarkerStyle\nis the only one (to my knowledge) that has the status of having been upgraded to\na proper Python class.\n\nBecause these implicit types are not classes in their own right, Matplotlib has\nhistorically had to roll its own solutions for centralizing documentation and\nvalidation of these implicit types (e.g. the `docstring.interpd.update` docstring\ninterpolation pattern and the `cbook._check_in_list` validator pattern,\nrespectively) instead of using the standard toolchains provided by Python\nclasses (e.g. docstrings and the validate-at-`__init__` pattern,\nrespectively).\n\nWhile these solutions have worked well for us, the lack of an explicit location\nto document each implicit type means that the documentation is often difficult\nto find, large tables of allowed values are repeated throughout the\ndocumentation, and often an explicit statement of the *scope* of an implicit\ntype is completely missing from the docs. Take the `plt.plot` docs, for\nexample: in the \"\"Notes\"\", a description of the matlab-like format-string styling\nmethod mentions `linestyle`, `color`, and `markers` options. There are\nmany more ways to pass these three values than are hinted at, but for many\nusers, this is their only source of understanding about what values are possible\nfor those options until they stumble on one of the relevant tutorials. A the\ntable of `Line2D` attributes is included in an attempt to show the reader what\noptions they have for controlling their plot. However, while the `linestyle`\nentry does a good job of linking to `Line2D.set_linestyle` (two clicks\nrequired) where the possible inputs are described, the `color` and `markers`\nentries do not. `color` simply links to `Line2D.set_color`, which fails to\noffer any intuition for what kinds of inputs are even allowed.\n\nIt could be argued that this is something that can be fixed by simply tidying up\nthe individual docstrings that are causing problems, but the issue is\nunfortunately much more systemic than that. Without a centralized place to find\nthe documentation, this will simply lead to us having more and more copies of\nincreasingly verbose documentation repeated everywhere each of these implicit\ntypes is used, making it especially more difficult for beginner users to simply\nfind the parameter that they need. However, the current system, which forces\nusers to slowly piece together their mental model of each implicit type through\nwiki-diving style traversal throughout our documentation, or piecemeal from\nStackOverflow examples, is also not sustainable.\n\n#### End Goal\n\nIdeally, any mention of an implicit type should link to a single page that\ndescribes all the possible values that type can take, ordered from most simple\nand common to most advanced or esoteric. Instead of using valuable visual\nspace in the top-level API documentation to piecemeal enumerate all the possible\ninput types to a particular parameter, we can then use that same space to give a\nplain-word description of what plotting abstraction the parameter is meant to\ncontrol.\n\nTo use the example of `linestyle` again, what we would want in the\n`LineCollection` docs is just:\n\n1. A link to complete docs for allowable inputs (a combination of those found in `Line2D.set_linestyle` and the [linestyle\n tutorial](https://matplotlib.org/3.2.2/gallery/lines_bars_and_markers/linestyles.html)).\n2. A plain words description of what the parameter is meant to accomplish. To matplotlib power users, this is evident from the parameter's name, but for new users this need not be the case.\n\nThe way this would look in the actual `LineCollection` docs is just\n``python\n\"\"\"\"\"\"\nlinestyles: `LineStyle` or list thereof, default: :rc:`lines.linestyle` ('-')\nA description of whether the stroke used to draw each line in the collection\nis dashed, dotted or solid, or some combination thereof.\n\"\"\"\"\"\"``\nwhere the `LineStyle` type reference would be resolved by Sphinx to point\ntowards the a single, authoritative, and complete set of documentation for how\nMatplotlib treats linestyles.\n\n#### Benefits\n\nSome powerful features of this approach include\n\n1. Making the complete extent of what each function is capable of obvious in plain text (with zero clicks required).\n2. Making the default option visible (with zero clicks). Seeing default option is often enough to jog the memory of returning users.\n3. Make a complete description of the \"\"most common\"\" and \"\"easiest\"\" options for a parameter easily available when browsing (with a single click).\n4. Make the process of discovering more powerful features and input methods as easy as \"\"scroll down\"\" to see more advanced options (with still only one click).\n5. Provide a centralized strategy for linking top-level \"\"API\"\" docs to the relevant \"\"tutorials\"\".\n6. Avoid API-doc-explosion, where scanning through the many possible options to each parameters makes individual docstrings unwieldy.\n\nOther benefits of this approach over the current docs are:\n\n1. Docs are less likely to become stale, due to centralization.\n2. Canonicalization of many of matplotlib's \"\"implicit standards\"\" (like what is a \"\"bounds\"\" versus an \"\"extents\"\") that currently have to be learned by reading the code.\n3. The process would highlight issues with API consistency in a way that can be more easily tracked via the GitHub issues tracker, helping with the process of improving our API.\n4. Faster doc build times, due to significant decreases in the amount of text needing to be parsed.\n\n#### Implementation\n\nThe improvements described above will require two major efforts for which a\ndedicated technical writer will be invaluable. The first is to create one\ncentralized \"\"tutorial\"\" page per implicit type. This will require working with\nthe core developer team to identify a concrete list of implicit types whose\ndocumentation would be valuable to users (typically, because they contain\npowerful, hidden features of our library whose documentation is currently only\nfound in difficult-to-stumble-across tutorials). For each implicit type, I will\nthen synthesize the various relevant tutorials, API docs, and example pages into\na single authoritative source of documentation that can be linked to anywhere\nthat particular type is referenced.\n\nOnce the centralized documentation for a given implicit type is complete, the\nsecond major effort begins: replacing existing API documentation with links to\nthe new documentation, with an eye towards making the experience of actually\nusing this new documentation as easy as possible, both for those using Python's\nbuilt-in `help()` utility and for those browsing our documentation online.\n\nWhile the exact format of the documentation proposed here is subject to change\nas this project evolves, I have worked with the *Matplotlib* core team during\ntheir weekly \"\"dev calls\"\" to establish a consensus that the strategy proposed\nhere is the most expedient, useful, and technically tractable approach to begin\ndocumenting these \"\"implicit types\"\" (notes on these\ncalls are available [on hackmd](https://hackmd.io/MNcskNfZSIOoLb50GqVIGg?view)).\nI will use the existing \"\"tutorials\"\" infrastructure for the initial stages of\ncreating the centralized documentation for each implicit type, allowing me to\neasily reference these pages as follows, without having to create any new public\nclasses (again, using the `LineCollection` docs as an example): \n\n \"\"\"\"\"\"\n linestyles: LineStyle or list thereof, default: :rc:`lines.linestyle` ('-')\n A description of whether the stroke used to draw each line in the collection\n is dashed, dotted or solid, or some combination thereof. For a full\n description of possible LineStyle's, see :doc:`tutorials/types/linestyle`.\n \"\"\"\"\"\"\n\nMoving forward, we could then easily change how these references are spelled\nonce the core developer team agrees on the best long-term strategy for\nincorporating our new \"\"types\"\" documentation into bona fide Python classes, for\nexample as proposed by me in [Matplotlib Enhancement Proposal\n30](https://github.com/matplotlib/matplotlib/pull/17446).\n\nFinally, the preliminary list of implicit types that I propose documenting\nduring this Google Season of Docs are:\n\n1. `capstyle`\n2. `joinstyle`\n3. `bounds`\n4. `extents`\n5. `linestyle`\n6. `colors`/`lists of colors`\n7. `colornorm/colormap`\n8. `tick formatters`\n\nA living version of this document can be found [on our\nDiscourse](https://discourse.matplotlib.org/t/improving-feature-discoverability-by-centralizing-documentation-of-implicit-types/21263)."]]