[Python-3000] rough draft signature PEP
Brett Cannon
brett at python.org
Mon Apr 24 22:26:45 CEST 2006
On 4/22/06, Talin <talin at acm.org> wrote:
> Brett Cannon <brett <at> python.org> writes:
>
> > [I am posting to python-3000 since this is where the parameter list
> > ideas are being discussed, but this is probably generic enough to
> > eventually make it into the 2.x line]
> >
> > Here is a rough draft of a PEP I wrote last summer after I had Guido
> > come for lunch at Google when I was interning there (i.e., a little
> > old =) . Someone (I think Philip) had suggested something like this
> > back then but it didn't go any farther. I liked the idea and I asked
> > Guido at lunch if he was okay for it; he was.
> >
> > So I wrote the following PEP along with a Python implementation
> > (attached, along with test cases). It is still a rough draft since I
> > am on vacation on top of visiting my dad for his birthday and thus
> > cannot put a ton of time into this at the moment, so don't consider
> > this a final version in any way. There is already a list of things to
> > consider and I am sure there are some things discussed during the new
> > parameter list ideas that could stand to be worked in. I am quite
> > happy to work on finishing this PEP so that Talin can focus on the
> > parameter list PEP. So just comment away and I will work on
> > incorporating them as time permits.
>
> Sounds good. A couple of comments:
>
> 1) I a still confused (see the "minor hitch" thread) as to how the signature
> information can be used without either duplicating the interpreter's
> parameter-binding algorithm, or somehow giving access to it.
>
> In other words, having access to signature information isn't very useful unless
> there is a straightforward and efficient way to map incoming arguments to
> specific signature slots. Because the decorators execute *before* this step
> normally happens, they can't just look and see which particular slot an argument
> got assigned to, they have to calculate it.
>
> The actual-to-formal mapping that's used in the interpreter itself can't be
> directly exposed, because it's not data driven (apparently - this is one of the
> parts of the intepreter that I don't understand yet.)
>
> A duplicate implementation suffers from two drawbacks: First, any implementation
> will need to be kept in sync with the interpreter. Second, the data structure
> that the mapping algorithm has to deal with (i.e. the signature object) is going
> to be in a form that is less efficient (i.e. since it needs to be constructable
> via Python code, it can't be a simple C structure like argument_ty.)
>
Honestly, I don't know how important this kind of functionality is.
Is it really that important to know ahead of time how arguments will
bind into the parameters? I originally came up with this for
documentation/introspection purposes, not to provide a way for people
to detect how bindings would end up.
As for the duplication of code if a function to do bindings was to
come into existence, that is just life. The C code used by the
interpreter could possibly be factored out if needed, but the binding
rules are not that complex as to need to worry too much about
duplicating it, especially if the signature object is coded in Python.
> 2) I noticed in your PEP that you followed the same mental model as is currently
> used in the compiler, which is that *args and **args are treated as special
> cases. In other words, the description of a function's arguments consists of an
> array of "regular" arguments, plus a couple of "special" argument fields.
>
> My mental model is a little different, as I tend to see the argument as a single
> list, where arguments have different modifiers, where * and ** are modifiers. In
> other word, my model follows more closely (IMHO) the way that arguments are read
> by the programmer.
>
Yeah, I see what you are saying. But I actually held this view long
before Iearned how Python did things underneath the covers.
I have no clue how people tend to view things. Anyone else care to
comment on how they tend to see arguments?
> To show the difference between the two models, lets create an algorithm that
> populates the parameter slots from a set of input arguments. For simplicity,
> lets just consider positional arguments, including varargs arguments.
>
> In the case where the varargs is considered a separate slot:
>
> i = 0
> while i < numInputArgs:
> if i <= regularSlotCount:
> slot[ i ] = args[ i ]
> i += 1
>
> if i < numInputArgs:
> slot[ i ] = args[ i: ]
>
> In the case where there's a single list:
>
> i = 0
> s = 0
> while i < numInputArgs:
> if modifiers[ s ] == VARARGS:
> slot[ s ].append( args[ i ] )
> else:
> slot[ s ] = args[ i ]
> s += 1
> i += 1
>
> (Note that neither of these functions is intended to be optimal.)
>
> I'm not saying that my model is necessarily better. Its just how I think about
> it. The only advantage that I would claim is that it more readily allows for
> future kinds of "special" arguments, by extending the meaning of the 'modifier'
> attribute.
>
> Here's what I had written in the PEP:
>
> Specification
>
> The specification defines a new function object attribute,
> __signature__, which contains a tuple containing a list of
> parameter descriptions.
>
> Each parameter description will be a tuple containing the
> following elements:
>
> [0] - The string name of the parameter.
Don't forget that can be a tuple as well.
> [1] - The Python type of the parameter, if a type has been
> specified. If none has been specified, this field will
> contain None.
> [2] - The parameter modifier (see below.)
> [3] - The default value of the parameter, if there is one.
>
> If there is no default value, then the 4th field will be absent -
> in other words, it will be a 3-tuple rather than a 4-tuple. This
> allows discrimination between a parameter whose default is 'None',
> and a parameter with no default.
>
I would change it to have a boolean value to flag if there is a
default and then have the field contain the default args since I would
like it all to work nicely with a genexp and filtering on whether a
field is True or False seems nicer than basing it on the length of the
tuple.
> The second argument, containing the Python type, will always
> contain None until such time as a convention for specifying
> explicit types is adopted.
>
> The parameter modifier is used to describe any modifier prefix
> characters attached to the argument, such as '*args'. The
> following table lists which values are currently defined:
>
> 0 - a regular argument (no modifiers)
> 1 - a varargs argument (one star)
> 2 - a keyword dict argument (two stars)
>
> Other values may be defined later as additions are made to the
> language.
As I said, I would like to hear how other people think. I have no
problem wrapping my head around to think like the rest of you (if it
happens to be the case) and view each argument as its own thing and
rework how the object represents things.
-Brett
More information about the Python-3000
mailing list