On Wed, Dec 08, 2021 at 11:50:55AM -0000, tmkehrenb...@gmail.com wrote:
> A few weeks ago, I proposed on this mailing list to write docstrings for
> class attributes like this:
> 
> @dataclass
> class A:
>     x: int
>     """Docstring for x."""
> 
> The main criticism, I think, was that it is weird to have the docstring
> *below* the attribute.

Why would it be weird to put a docstring below the object that owns it? 
We already do that for class and function signatures.

    def func():
        """Docstring is below the signature"""

I would strongly prefer to have the docstring follow the attribute, like 
function and class docstrings follow the signature, not lead it.

 
> To solve this problem, I propose to introduce a new kind of string: a
> d-string

Not another string prefix :-(


> A d-string is a normal string, except that it is stored in __attrdoc__ 
> when used inside a class. It is stored with the name of the variable 
> *below* it as the key.


I'd like to suggest an alternative syntax that doesn't need a new string 
prefix, although it does require new syntax. I think it is fully 
backwards compatible.

Rather than implicitly linking a bare string to the following (or 
previous?) attribute, this would explicitly link them by putting them on 
the same line (at least for short docstrings).

Full declaration syntax becomes:

    name : Type = value : docstring_expression

with the various parts being optional. Example:


    @dataclass
    class InventoryItem:
        """Class for keeping track of an item in inventory."""

        name: str : "Short name of the item"
        unit_price: float : "Price per unit in dollar."
        quantity_on_hand: int = 0 : (
            "Available quantity currently in the warehouse.")


The docstring expression could evaluate to any value, not necessarily a 
string, but conventionally one would use a string, and I expect style 
guides would discourage or ban non-strings. (But see below for a 
possible objection.)

Aside from the name, each part of the syntax is optional:

    # Type hint only.
    name: Type

    # Assignment only.
    name = value

    # Declare a type hint, and a docstring.
    name: Type : docstring

    # Assign a value, and a docstring, with no type hint.
    name = value : docstring

    # And all three: type hint, value and docstring.
    name: Type = value : docstring


If this makes sense, one might even have an attribute with no type hint 
or value, only a docstring:

    name : : docstring

which would assign the docstring to `__attrdoc__` but otherwise have no 
effect.

Formatting long lines could be done either with parentheses as in the 
quantity_on_hand example above, or backslashes for those who don't hate 
them:

        quantity_on_hand: \
            int = 0 : \
            "Available quantity currently in the warehouse."


Strings of course can use any prefix, raw strings, f-strings, triple- 
quoted strings, whatever you like. Since the docstring part is just an 
expression, it doesn't need to be a string literal.

If people object to the "arbitrary expression" part as too YAGNI, we 
could limit the docstring part to be:

* a string literal (using any prefix);
* an f-string;
* or one of the above, parenthesed.

And maybe even drop the f-string and just allow an string literal, 
optionally with parentheses.


-- 
Steve
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/3KNFCJF2T6KOUHM6YMVXTCS6C2OHDQGG/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to