Grupos de Google ya no admite nuevas publicaciones ni suscripciones de Usenet. El contenido anterior sigue siendo visible.

Friday Finking: Docstrings and DataClasses

Visto 37 veces
Saltar al primer mensaje no leído

dn

no leída,
27 nov 2021, 1:16:3427/11/21
a
How have you updated your (team's) standards and conventions for
docstrings, when using dataclasses?


NB the question is specifically class-related. Whereas many of the
examples 'here' are of functions; a docstring is a docstring, is a
docstring.


The original word on the subject is/was "PEP 257 -- Docstring
Conventions" (https://www.python.org/dev/peps/pep-0257/) and included
suggestions such as:

def complex(real=0.0, imag=0.0):
"""Form a complex number.

Keyword arguments:
real -- the real part (default 0.0)
imag -- the imaginary part (default 0.0)
"""
if imag == 0.0 and real == 0.0:
return complex_zero
...

The key information is the purpose of the function. We also find a
re-statement of the parameter names, their default-values, an intimation
of their types, and an indication of their purpose.

NB no mention of the output/return-value's specifics.


This format plays-nicely with the Python help() system and related.


Barely one year later the topic was advanced, with the more detailed
"PEP 287 -- reStructuredText Docstring Format"
(https://www.python.org/dev/peps/pep-0287/).

This idea is better-illustrated in "The Sphinx docstring format"
(https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html).

That offers a template:

"""[Summary]

:param [ParamName]: [ParamDescription], defaults to [DefaultParamVal]
:type [ParamName]: [ParamType](, optional)
...
:raises [ErrorType]: [ErrorDescription]
...
:return: [ReturnDescription]
:rtype: [ReturnType]
"""

...with practical-example docstrings written for "the SimpleBleDevice
class, which is defined within our simpleble module":

class SimpleBleDevice(object):
"""This is a conceptual class representation of a simple BLE device
(GATT Server). It is essentially an extended combination of the
:class:`bluepy.btle.Peripheral` and :class:`bluepy.btle.ScanEntry`
classes

:param client: A handle to the :class:`simpleble.SimpleBleClient` client
object that detected the device
:type client: class:`simpleble.SimpleBleClient`
:param addr: Device MAC address, defaults to None
:type addr: str, optional
:param addrType: Device address type - one of ADDR_TYPE_PUBLIC or
ADDR_TYPE_RANDOM, defaults to ADDR_TYPE_PUBLIC
:type addrType: str, optional
:param iface: Bluetooth interface number (0 = /dev/hci0) used for the
connection, defaults to 0
:type iface: int, optional
:param data: A list of tuples (adtype, description, value)
containing the
AD type code, human-readable description and value for all available
advertising data items, defaults to None
:type data: list, optional
:param rssi: Received Signal Strength Indication for the last received
broadcast from the device. This is an integer value measured in dB,
where 0 dB is the maximum (theoretical) signal strength, and more
negative numbers indicate a weaker signal, defaults to 0
:type rssi: int, optional
:param connectable: `True` if the device supports connections, and
`False`
otherwise (typically used for advertising ‘beacons’).,
defaults to `False`
:type connectable: bool, optional
:param updateCount: Integer count of the number of advertising packets
received from the device so far, defaults to 0
:type updateCount: int, optional
"""

(apologies: email word-wrap likely wrecks their neat formatting)


We've probably reached the point-in-time when this 'grumpy old man'
bemoans that such formulaic approaches tend to lead to slavish habits -
which become vices when they do nothing to improve the intended
objectives of "readability" (or worse detract from it), ie the docstring
equivalent of:

counter += 1 # add one to counter


Management advice: if you set a standard/requirement, such will be met -
without regard for other measures of quality, ie be careful what you
wish for!


Why the negative attitude? An example published in "Python Docstrings :
How to document your Python code ?"
(https://amiradata.com/python-docstrings/):

def setType(self,type):
"""Change the pokemon type.

The parameter value is stored in the type
variable of the pokemon class.

:param type: type pokemon
:type type: string
:return: no value
:rtype: none
"""

self.type = type
return

return self.type

NB are you also amused by the inclusion of a question-mark in the
article's title?

The use of the name "type", alongside the Python term "type", adds to my
confusion (because I didn't/don't even know that there is more than one
type/kind/flavor of Pokemon (mea culpa!)). To say nothing of the
multiple return statements and non-PEP-008 naming.


Fast-forward a good 15 years and today we have 'typing' (many PEP-refs)
and "PEP 557 -- Data Classes"
(https://www.python.org/dev/peps/pep-0557/), which combined to become
the "Data Classes" library in the PSL
(https://docs.python.org/3/library/dataclasses.html)

Now we can write:

@dataclass
class InventoryItem:
"""Class for keeping track of an item in inventory."""
name: str
unit_price: float
quantity_on_hand: int = 0

The docstring itself still covers the purpose of the function.

In this case, there is no re-statement of the parameter names (which
would otherwise have appeared in __init__()), because their declaration
is immediately beneath the docstring.

As are any default-values.

The parameter-typing has become a compulsory part of the code (cf
added-documentation).

All we appear to be missing is an indication of each parameter's purpose
- over-and-above any meaning which can be gleaned from the careful
choice of attribute-name.

Plus, if we add return-value typing to a function def, then that need is
similarly satisfied.

Yes, I'm a strong user of typing (but not always)...


Finally, to the strong-arm tactics that linters seem to have become:

I'm amused (ok, it irritates) that one of the linters built-in or
plugged-into my IDE does not like in-line comments. No place, no time!@
Accordingly, the following results in criticism:

unit_price: float # the cost of a single unit in NZD
quantity_on_hand: int = 0 # excludes items reserved by Sales Dept

Yet, such seems a quite-reasonable (updated for dataclasses) approach.


Do you agree?

Do you not bother with docstring style at all?

Have you stuck with PEP-257, after all these years?

Do you (still) use the Sphinx/RST format for docstrings, even though it
seems even more repetitive and wordy?

Have you updated your conventions/style-manual to acknowledge
dataclasses? If so, how?
--
Regards,
=dn

Julio Di Egidio

no leída,
27 nov 2021, 5:45:4227/11/21
a
On 27/11/2021 07:15, dn wrote:

> How have you updated your (team's) standards and conventions for
> docstrings, when using dataclasses?

Nope: while writing code that works with the tools is important,
conventions on code docs or other we develop in-house along the time and
it's not an article or even a PEP that is going to override that...

> We've probably reached the point-in-time when this 'grumpy old man'
> bemoans that such formulaic approaches tend to lead to slavish habits -

Especially, I would note, if they are taken as normative, or even as
best practices, when they apparently aren't.

> which become vices when they do nothing to improve the intended
> objectives of "readability" (or worse detract from it), ie the docstring
> equivalent of:
>
> counter += 1 # add one to counter

I agree on that 100%, i.e. doc strings to actually document the code,
though a "problem", or at least an added requirement, nowadays is that
indeed tools also need support (not just for static checkers and
analysers, but also intellisense and what-not: all the more so in Python
where a formal notation for types is simply not yet ready for
production), which certainly adds to the level of formality and
verbosity imposed.

(In fact, I think the level of formality in nowadays software production
is way too low and we should rather strive for formal methods, but by
that I certainly do not mean bureaucracy or verbosity...)

> Management advice: if you set a standard/requirement, such will be met -
> without regard for other measures of quality, ie be careful what you
> wish for!

Again, +1 indeed.

> I'm amused (ok, it irritates) that one of the linters built-in or
> plugged-into my IDE does not like in-line comments. No place, no time!@
> Accordingly, the following results in criticism:

Indeed, but linters aren't any ultimate source of code quality measure
either, indeed I'd rather find the linter that supports the
configuration I need, if there is one, otherwise I'll do without... (as
a strategy, I don't mean it's easy judgements/decisions).

> Do you not bother with docstring style at all?

I would use all the usual "fields", i.e. description, in/out arguments,
any implementation notes, in fact also the exceptions that might get
raised and (succinctly/generically) why... so the usual full recipe,
just only to the point and to the level of detail that is actually
warranted by code complexity on a side, and, as said, the tools in use
(or other "external" requirements) on the other. In particular, unless
constrained otherwise, I would only put the "fields" that I actually
need: for example, descriptions or the list of arguments are indeed
useless in most places as long as naming is appropriate...

My 2c.

Julio
0 mensajes nuevos