
On Wed, Dec 08, 2021 at 11:50:55AM -0000, tmkehrenberg@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