[Python-3000] rough draft signature PEP

Talin talin at acm.org
Sun Apr 23 08:41:10 CEST 2006


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.)

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.

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.
        [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.
    
    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.
    
-- Talin




More information about the Python-3000 mailing list