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

Peter O'Connor peter.ed.oconnor at gmail.com
Sun Apr 28 14:48:31 EDT 2019


Thanks all for the responses. I read thought them carefully and address
each below.

I don't think any fully address the core problem - The "Argument" - the
tuple of (type, default, documentation) - is currently not a first-class
entity.  Because there is no way to reference an Argument, there is much
copypasta and dangerous-default-duplication.  The idea of this proposal is
that it should be possible to define an argument in one place, and simply
bind a different name to it in each function signature.

To recap - the points to the proposal are:
- Allow documentation to be bound to an argument: "func(arg_a: int = 3 ?
'doc about arg', ...)" or "func(arg_a: int = 3 # 'doc about arg', ...)"
- Allow reference to argument: "outer_func(new_arg_a_name:
func.args.arg_a.type = func.args.arg_a.default ? 'new doc for arg a', ...)"
- (optionally) a shorthand syntax for reusing type/doc/default of argument:
"def outer_func(new_arg_a_name :=? func.args.arg_a, ...):"

Below I have responded to each comment - please let me know if I missed
something:

----------

On Thu, Apr 25, 2019 at 3:59 PM Robert Vanden Eynde <robertve92 at gmail.com>
wrote:

> Looks like a more complicated way to say :
> def f(x:'int : which does stuff' = 5, y:'int : which does more stuffs')
>

I hadn't though of incorporating documentation into the type, that's a nice
idea.  I think it's an ok "for now" solution but:
- doing it this way loses the benefits of type inspection (built in to most
IDEs now),
- does not allow you do for instance keep the type definition in the
wrapper while changing the documentation.
- Provides no easy way to reference (f.args.x.documentation) which is a
main point to the proposal.

----------

On Thu, Apr 25, 2019 at 3:58 PM Chris Angelico <rosuav at gmail.com> wrote:

> @functools.passes_args(f)
> def wrapper(spam, ham, *a, **kw):
>     f(*a, **kw)
> ....

If that were implemented, would it remove the need for this new syntax
> you propose?
>

This does indeed allow defaults and types to be passed on, but I find a
this approach still has the basic flaw of using **kwargs:
- It only really applies to "wrappers" - functions that wrap another
function.  The goal here is to address the common case of a function
passing args to a number of functions within it.
- It is assumed that the wrapper should use the same argument names as the
wrapped function.  A name should bind a function to an argument - but here
the name is packaged with the argument.
- It remains difficult to determine the arguments of "wrapper" by simple
inspection - added syntax for removal of certain arguments only complicates
the task and seems fragile (lest the wrapped functions argument names
change).
- Renaming an argument to "f" will change the change the arguments of
wrapper - but in a way that's not easy to inspect (so for instance if you
have a call "y = wrapper(arg_1=4)", and you change "f(arg1=....)" to
"f(arg_one=...)" no IDE will catch that and make the appropriate change to
"y=wrapper(arg_one=4)".
- What happens if you're not simply wrapping one sub-function but calling
several?  What about when those subfunctions have arguments with the same
name?

----------

On Thu, Apr 25, 2019 at 5:50 PM David Mertz <mertz at gnosis.cx> wrote:

> Why not just this in existing Python:
>     def func_1(
>             a: int = 1 # 'Something about param a',
>             b: float = 2.5 # 'Something else about param b',
>             ) -> float:
>         """Something about func_1
>
>         a and b interact in this interesting way.
>         a should be in range 0 < a < 125
>         floor(b) should be a prime number
>
>         Something about return value of func_1
>         returns a multiplication
>         """
>         return a*b
>

- This would currently be a syntax error (because "#" is before the comma),
but sure we could put it after the comma.
- It does not address the fact that we cannot reference "func_1.a.default"
- which is one of the main points of this proposal.
- I'm fine with "#" being the documentation operator instead of "?", but
figured people would not like it because it breaks the precedent of
anything after "#" being ignored by the compiler

---------------

On Thu, Apr 25, 2019 at 9:04 PM Anders Hovmöller <boxed at killingar.net>
wrote:

> Maybe something like...
> def foo(**kwargs):
>     “””
>     @signature_by:
> full.module.path.to.a.signature_function(pass_kwargs_to=bar,
> hardcoded=[‘quux’])
>     “””
>     return bar(**kwargs, quux=3)
>

This makes it difficult to see what the names of arguments to "foo" are, at
a glance.  And what happens if (as in the example) "foo" does not simply
wrap a function, but distributes arguments to multiple subfunctions? (this
is a common case)

----------------------------

On Fri, Apr 26, 2019 at 2:18 AM Stephen J. Turnbull <
turnbull.stephen.fw at u.tsukuba.ac.jp> wrote:

> What I would rather see is
>
> (1) Comment syntax "inside" (fvo "inside" including any comment after
>     the colon but before docstring or other code) .....
>
> (2) asserts involving parameters lexically are available to help().....
>

(1) I'm fine with "#" being used instead of "?" as the "documentation
operator", but I figured it would be rejected for breaking the president
that everything after "#" is ignored by the compiler.
(2) This would be a nice addition ... if this proposal were actually
implemented, you'd have a built in "Argument" object, and in that case you
could do e.g.:
    RGB_IMAGE = Argument(type=np.ndarray, doc = 'An RGB image', check =
lambda img: (img.ndim==3 and img.shape[2]==3))
    def brighten_image(image :=? RGB_IMAGE, ...):
        ...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20190428/a2f22f63/attachment.html>


More information about the Python-ideas mailing list