Use typing.Annotated to provide a docstring for variables.

I originally wrote an answer (see below) where I said this wasn't possible. That was true back in 2012 but Python has moved on. Today you can provide the equivalent of a docstring for a global variable or an attribute of a class or instance. You will need to be running at least Python 3.9 for this to work:

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

You can access the annotations at run time using 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']}

Extract information about variables using the hints for the module or class where they were declared. Notice how the annotations combine when you nest them:

>>> hints['legal_limit'].__metadata__
('miles per hour', 'UK national limit for single carriageway')
>>> hints['day']
typing.Annotated[float, 'seconds']

It even works for variables that have type annotations but have not been assigned a value. If I tried to reference calc.current_speed I would get an attribute error but I can still access its metadata:

>>> hints['current_speed'].__metadata__
('miles per hour',)

The type hints for a module only include the global variables, to drill down you need to call get_type_hints() again on functions or classes:

>>> 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']}

I only know of one tool so far that can use typing.Annotated to store documentation about a variable and that is Pydantic. It is slightly more complicated than just storing a docstring though it actually expects an instance of pydantic.Field. Here's an example:

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",
    )

Using the model class:

>>> 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 models can give you a JSON schema:

>>> 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'}
>>> 

If you use this class in a FastAPI application the OpenApi specification has example and description for all three of these taken from the relevant Field.

And here's the original answer which was true back then but hasn't stood the test of time:

No, it is not possible and it wouldn't be useful if you could.

The docstring is always an attribute of an object (module, class or function), not tied to a specific variable.

That means if you could do:

t = 42
t.__doc__ = "something"  # this raises AttributeError: '__doc__' is read-only

you would be setting the documentation for the integer 42 not for the variable t. As soon as you rebind t you lose the docstring. Immutable objects such as numbers of strings sometimes have a single object shared between different users, so in this example you would probably actually have set the docstring for all occurences of 42 throughout your program.

print(42 .__doc__) # would print "something" if the above worked!

For mutable objects it wouldn't necessarily be harmful but would still be of limited use if you rebind the object.

If you want to document an attribute of a class then use the class's docstring to describe it.

Answer from Duncan on Stack Overflow
Top answer
1 of 10
143

Use typing.Annotated to provide a docstring for variables.

I originally wrote an answer (see below) where I said this wasn't possible. That was true back in 2012 but Python has moved on. Today you can provide the equivalent of a docstring for a global variable or an attribute of a class or instance. You will need to be running at least Python 3.9 for this to work:

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

You can access the annotations at run time using 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']}

Extract information about variables using the hints for the module or class where they were declared. Notice how the annotations combine when you nest them:

>>> hints['legal_limit'].__metadata__
('miles per hour', 'UK national limit for single carriageway')
>>> hints['day']
typing.Annotated[float, 'seconds']

It even works for variables that have type annotations but have not been assigned a value. If I tried to reference calc.current_speed I would get an attribute error but I can still access its metadata:

>>> hints['current_speed'].__metadata__
('miles per hour',)

The type hints for a module only include the global variables, to drill down you need to call get_type_hints() again on functions or classes:

>>> 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']}

I only know of one tool so far that can use typing.Annotated to store documentation about a variable and that is Pydantic. It is slightly more complicated than just storing a docstring though it actually expects an instance of pydantic.Field. Here's an example:

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",
    )

Using the model class:

>>> 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 models can give you a JSON schema:

>>> 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'}
>>> 

If you use this class in a FastAPI application the OpenApi specification has example and description for all three of these taken from the relevant Field.

And here's the original answer which was true back then but hasn't stood the test of time:

No, it is not possible and it wouldn't be useful if you could.

The docstring is always an attribute of an object (module, class or function), not tied to a specific variable.

That means if you could do:

t = 42
t.__doc__ = "something"  # this raises AttributeError: '__doc__' is read-only

you would be setting the documentation for the integer 42 not for the variable t. As soon as you rebind t you lose the docstring. Immutable objects such as numbers of strings sometimes have a single object shared between different users, so in this example you would probably actually have set the docstring for all occurences of 42 throughout your program.

print(42 .__doc__) # would print "something" if the above worked!

For mutable objects it wouldn't necessarily be harmful but would still be of limited use if you rebind the object.

If you want to document an attribute of a class then use the class's docstring to describe it.

2 of 10
126

Epydoc allows for docstrings on variables:

While the language doesn't directly provides for them, Epydoc supports variable docstrings: if a variable assignment statement is immediately followed by a bare string literal, then that assignment is treated as a docstring for that variable.

Example:

class A:
    x = 22
    """Docstring for class variable A.x"""

    def __init__(self, a):
        self.y = a
        """Docstring for instance variable A.y"""
🌐
SourceForge
epydoc.sourceforge.net › manual-docstring.html
Python Docstrings - Epydoc
For more information about Python docstrings, see the Python Tutorial or the O'Reilly Network article Python Documentation Tips and Tricks. Python don't support directly docstrings on variables: there is no attribute that can be attached to variables and retrieved interactively like the __doc__ ...
Discussions

Add docstrings to variables in TypedDicts?
Just reading through SO posts, it seems this isn’t possible: class MyClass(TypedDict): """runtime config""" r_config: bool And get a docstring, for each variable defined within. Is there plans to add this or workarounds people use? I’m aware one could document all together in a class, but ... More on discuss.python.org
🌐 discuss.python.org
4
0
December 19, 2024
docstring for variable?
Creating a docstring for a specific variable is kind of unusual, but here's a SO answer on how to do it (requires Python 3.9) https://stackoverflow.com/questions/8820276/docstring-for-variable More on reddit.com
🌐 r/learnpython
4
1
March 2, 2021
Python DocString (Google Style): How to document class attributes? - Stack Overflow
Currently, in the Google Style Docstrings Example, the class ExamplePEP526Class example states · If the class has public attributes, they may be documented here in an Attributes section and follow the same formatting as a function's Args section. If napoleon_attr_annotations is True, types can be specified in the class body using PEP 526 annotations. PEP 526 added variable ... More on stackoverflow.com
🌐 stackoverflow.com
Docstrings for variables from doc-comments above
I see that module_variable = 1 """Docstring for module_variable.""" works for giving the module_variable a docstring. Is there anyway that something like this could al... More on github.com
🌐 github.com
5
December 16, 2020
Top answer
1 of 6
135

In short: class attributes cannot have doc strings in the way that classes and functions have.

To avoid confusion, the term property has a specific meaning in python. What you're talking about is what we call class attributes. Since they are always acted upon through their class, I find that it makes sense to document them within the class' doc string. Something like this:

class Albatross(object):
    """A bird with a flight speed exceeding that of an unladen swallow.

    Attributes:
        flight_speed     The maximum speed that such a bird can attain.
        nesting_grounds  The locale where these birds congregate to reproduce.
    """
    flight_speed = 691
    nesting_grounds = "Throatwarbler Man Grove"

I think that's a lot easier on the eyes than the approach in your example. If I really wanted a copy of the attribute values to appear in the doc string, I would put them beside or below the description of each attribute.

Keep in mind that in Python, doc strings are actual members of the objects they document, not merely source code annotations. Since class attribute variables are not objects themselves but references to objects, they have no way of holding doc strings of their own. I guess you could make a case for doc strings on references, perhaps to describe "what should go here" instead of "what is actually here", but I find it easy enough to do that in the containing class doc string.

2 of 6
108

The other answers are very outdated. PEP-257 describes how you can use docstrings for attributes. They come after the attribute, weirdly:

String literals occurring elsewhere in Python code may also act as documentation. They are not recognized by the Python bytecode compiler and are not accessible as runtime object attributes (i.e. not assigned to __doc__), but two types of extra docstrings may be extracted by software tools:

  1. String literals occurring immediately after a simple assignment at the top level of a module, class, or __init__ method are called “attribute docstrings”.
class C:
    "class C doc-string"

    a = 1
    "attribute C.a doc-string (1)"

    b = 2
    "attribute C.b doc-string (2)"

It also works for type annotations like this:

class C:
    "class C doc-string"

    a: int
    "attribute C.a doc-string (1)"

    b: str
    "attribute C.b doc-string (2)"

VSCode supports showing these.

🌐
Programiz
programiz.com › python-programming › docstrings
Python Docstrings (With Examples)
For example, "I am a single-line comment" ''' I am a multi-line comment! ''' print("Hello World") Note: We use triple quotation marks for multi-line strings. ... As mentioned above, Python docstrings are strings used right after the definition of a function, method, class, or module (like in ...
🌐
Readthedocs
pydoctor.readthedocs.io › en › latest › codedoc.html
How to Document Your Code — pydoctor documentation
In Python, a string at the top of a module, class or function is called a docstring. For example: """This docstring describes the purpose of this module.""" class C: """This docstring describes the purpose of this class.""" def m(self): """This docstring describes the purpose of this method.""" ...
🌐
Noirlab
datalab.noirlab.edu › docs › manual › DevGuide › DocumentingPythonAPIswithDocstrings › DocumentingPythonAPIswithDocstrings.html
3.2. Documenting Python APIs with Docstrings — Data Lab documentation
Constants in modules and attributes ... structure with these sections: ... Docstrings for module-level variables and class attributes appear directly below their first declaration....
🌐
Python.org
discuss.python.org › python help
Add docstrings to variables in TypedDicts? - Python Help - Discussions on Python.org
December 19, 2024 - Just reading through SO posts, it seems this isn’t possible: class MyClass(TypedDict): """runtime config""" r_config: bool And get a docstring, for each variable defined within. Is there plans to add this or worka…
Find elsewhere
🌐
Reddit
reddit.com › r/learnpython › docstring for variable?
r/learnpython on Reddit: docstring for variable?
March 2, 2021 -

I can find nothing on how to add a docstring to a variable, so I'm assuming it's just not available (other than direct assignment maybe?), but maybe someone knows...when all tutorials on the matter apparently skip this feature? :p

When I run help on it I get the docstring for the class, so maybe there's a hack to be had there, but I'd rather them be independent.

Indenting a string right below the variable causes parse error. Leaving it unindented does not attach it to the variable. That's all I know to try.

🌐
Python
peps.python.org › pep-0257
PEP 257 – Docstring Conventions | peps.python.org
The docstring for a class should summarize its behavior and list the public methods and instance variables. If the class is intended to be subclassed, and has an additional interface for subclasses, this interface should be listed separately ...
🌐
Lsst
developer.lsst.io › v › DM-15183 › python › numpydoc.html
Documenting Python APIs with Docstrings — LSST DM Developer Guide DM-15183 documentation
Constants in modules and attributes ... structure with these sections: ... Docstrings for module-level variables and class attributes appear directly below their first declaration....
🌐
Python
peps.python.org › pep-0224
PEP 224 – Attribute Docstrings | peps.python.org
August 23, 2000 - class C: "C doc string" b = 2 def x(self): "C.x doc string" y = 3 return 1 "b's doc string" Since the definition of method “x” currently does not reset the used assignment name variable, it is still valid when the compiler reaches the docstring “b’s doc string” and thus assigns the string to __doc_b__. A possible solution to this problem would be resetting the name variable for all non-expression nodes in the compiler.
🌐
JetBrains
youtrack.jetbrains.com › issue › PY-40634 › Docstrings-for-module-level-variables-and-class-attributes-should-be-highlighted-as-docstrings
Docstrings for module-level variables and class attributes ...
Our website uses some cookies and records your IP address for the purposes of accessibility, security, and managing your access to the telecommunication network. You can disable data collection and cookies by changing your browser settings, but it may affect how this website functions.
🌐
Readthedocs
sphinxcontrib-napoleon.readthedocs.io › en › latest › example_google.html
Example Google Style Python Docstrings — napoleon 0.7 documentation
Attributes: msg (str): Human readable string describing the exception. code (int): Exception error code. """ def __init__(self, msg, code): self.msg = msg self.code = code class ExampleClass(object): """The summary line for a class docstring should fit on one line.
🌐
STechies
stechies.com › python-docstrings
Python: Docstrings
A docstring in Python is a way to provide an explanation along with functions, modules, and classes. They are documentation strings that are used as comments. These strings are not assigned to any variables.
Top answer
1 of 2
8

Assuming you would like to use napoleon to render your docstrings into docs, the sphinx developers are working towards a way to add custom sections to class-level docstrings (see Issue #33).

Currently, in the Google Style Docstrings Example, the class ExamplePEP526Class example states

If the class has public attributes, they may be documented here in an Attributes section and follow the same formatting as a function's Args section. If napoleon_attr_annotations is True, types can be specified in the class body using PEP 526 annotations.

PEP 526 added variable annotations to type hints. Hence, your code could now be written:

"""Sandbox module"""

class Toto:
    """ This class is an example

    Attributes:
        class_attribute (str): (class attribute) The class attribute
        instance_attribute (str): The instance attribute
    """

    class_attribute: str = ""

    def __init__(self):
        self.instance_attribute: str = ""

For one thing, it seems you forgot to put the type hint str after class_attribute when defining it, so mypy (if using an external type checker) probably couldn't discover its type.

Ironically, the reverse situation would have worked: in napoleon version 3.4, if napoleon_attr_attributes is set to True, then

If an attribute is documented in the docstring without a type and has an annotation in the class body, that type is used.

Second, the pass at the end of your __init__ method is allowed, but unnecessary since you define instance_attribute there.

I mention Issue #33 because, personally, I would rather call the heading "Class Variables" as "Attributes" by itself doesn't distinguish between instance vs. class attributes/variables. For the time being, you may want to put your own notation in the attribute description like I have done.

For me, I either have fewer class attributes than instance attributes or none at all, so I only note if an attribute is a class attribute (otherwise, it is an instance attribute). That way, I don't have to write (instance attribute) next to all my instance attributes. Alternatively, you could try putting class in the parentheses with the type the same what that optional is listed:

class_attribute (str, class): The class attribute

I'm not sure if that will work or break. If it breaks, it would certainly be nice to have added to the docstring syntax in the future (I think this looks cleaner).

Lastly, you could document the class variable as an attribute docstring as defined in PEP 257 as well as this SO answer by putting a docstring directly underneath the assignment like so:

"""Sandbox module"""

class Toto:

    class_attribute: str = ""
    """class_attribute (str): (class attribute) The class attribute"""

    def __init__(self):
        """ This class is an example
    
        Attributes:
            instance_attribute (str): The instance attribute
        """
        self.instance_attribute: str = ""
2 of 2
-2

Try this:

"""
    Sandbox module
    ~~~~~~~~~~~~~~
"""

class Toto:
    """This class is an example

    Attributes:
        instance_attribute (str): The instance attribute #OK
    """
    
    #: str: The class attribute #Unresolved reference
    class_attribute = ""

    def __init__(self):
        self.instance_attribute = ""
        pass

This works fine for me using sphinx.

🌐
GitHub
github.com › pdoc3 › pdoc › issues › 289
Docstrings for variables from doc-comments above · Issue #289 · pdoc3/pdoc
December 16, 2020 - I see that module_variable = 1 """Docstring for module_variable.""" works for giving the module_variable a docstring. Is there anyway that something like this could al...
Author: pdoc3
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-docstrings
Python Docstrings - GeeksforGeeks
September 19, 2025 - Note: Docstrings are actually strings too, but Python treats them specially when placed right after a function, class or module definition. Example: This example shows the difference between a comment, a string and a docstring. ... # This is a comment (ignored by Python) name = "Daniel" # A string assigned to a variable def greet(): """This is a docstring.
🌐
Lsst
developer.lsst.io › v › DM-7919 › docs › py_docs.html
Documenting Python APIs — LSST DM Developer Guide latest documentation
Returns ------- sum : `float` Sum of `values`. """ pass · Like method and function docstrings, the docstring should immediately follow the class definition, without a blank space. However, there should be a single blank line before following code such as class variables or the __init__ method.
🌐
DataCamp
datacamp.com › tutorial › docstrings-python
Python Docstrings Tutorial : Examples & Format for Pydoc, Numpy, Sphinx Doc Strings | DataCamp
February 14, 2025 - Python documentation string, commonly known as docstring, is a string literal, and it is used in the class, module, function, or method definition. Docstrings are accessible from the doc attribute (__doc__) for any of the Python objects and also with the built-in help() function.
🌐
Pdoc3
pdoc3.github.io › pdoc › doc › pdoc
pdoc API documentation
In the default HTML template, such inherited docstrings are greyed out. Python by itself doesn't allow docstrings attached to variables. However, pdoc supports documenting module (or global) variables, class variables, and object instance variables via two different mechanisms: PEP-224 and ...