[Python-ideas] Proposal: "?" Documentation Operator and easy reference to argument types/defaults/docstrings

Peter O'Connor peter.ed.oconnor at gmail.com
Thu Apr 25 18:41:10 EDT 2019


Dear all,

Despite the general beauty of Python, I find myself constantly violating
the "don't repeat yourself" maxim when trying to write clear, fully
documented code.  Take the following example:

    def func_1(a: int = 1, b: float = 2.5) -> float:
        """
        Something about func_1
        :param a: Something about param a
        :param b: Something else about param b
        :return: Something about return value of func_1
        """
        return a*b

    def func_2(c:float=3.4, d: bool =True) -> float:
        """
        Something about func_2
        :param c: Something about param c
        :param d: Something else about param d
        :return: Something about return value
        """
        return c if d else -c

    def main_function(a: int = 1, b: float = 2.5, d: bool = True) -> float:
        """
        Something about main_function
        :param a: Something about param a
        :param b: Something else about param b
        :param d: Something else about param d
        :return: Something about return value
        """
        return func_2(func_1(a=a, b=b), d=d)

Which has the following problems:
- Defaults are defined in multiple places, which very easily leads to bugs
(I'm aware of **kwargs but it obfuscates function interfaces and usually
does more harm than good)
- Types are defined in multiple places
- Documentation is copy-pasted when referencing a single thing from
different places.  (I can't count the number of types I've written ":param
img: A (size_y, size_x, 3) RGB image" - I could now just reference a single
RGB_IMAGE_DOC variable)
- Argument names need to be written twice - in the header and documentation
- and it's up to the user / IDE to make sure they stay in sync.

I propose to resolve this with the following changes:
- Argument/return documentation can be made inline with a new "?"
operator.  Documentation becomes a first class citizen.
- Argument (type/default/doc) can be referenced by "func.args.<arg_name>.type"
/ "func.args.<arg_name>.default" / "func.args.<arg_name>.doc".  Positional
reference: e.g. "func.args[1].default" also allowed.  If not specified,
they take a special, built-in "Undefined" value (because None may have
another meaning for defaults).  Return type/doc can be referenced with
"func.return.type"
/ "func.return.doc".

This would result in the following syntax:

    def func_1(
            a: int = 1 ? 'Something about param a',
            b: float = 2.5 ? 'Something else about param b',
            ) -> float ? 'Something about return value of func_1':
        """ Something about func_1 """
        return a*b

    def func_2(
            c: float=3.4 ? 'Something about param c',
            d: bool =True ? 'Something else about param d',
            ) -> float ? 'Something about return value':
        """ Something about func_2 """
        return c if d else -c

    def main_function(
            a: func_1.args.a.type = func_1.args.a.default ?
func_1.args.a.doc,
            b: func_1.args.b.type = func_1.args.b.default ?
func_1.args.b.doc,
            d: func_2.args.d.type = func_2.args.d.default ?
func_2.args.d.doc,
            ) -> func_2.return.type ? func2.return.doc:
        """ Something about main_function """
        return func_2(func_1(a=a, b=b), d=d)

If the main_function header seems repetitious (it does) we could allow for
an optional shorthand notation like:

    def main_function(
            a :=? func_1.args.a,
            b :=? func_1.args.b,
            d :=? func_2.args.d,
            ) ->? func_2.return:
        """ Something about main_function """
        return func_2(func_1(a=a, b=b), d=d)

Where "a :=? func_1.args.a" means "argument 'a' takes the same
type/default/documentation as argument 'a' of func_1".

So what do you say?  Yes it's a bold move, but I think in the long term
it's badly needed.  Perhaps something similar has been proposed already
that I'm not aware of.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20190425/03791bed/attachment.html>


More information about the Python-ideas mailing list