On 9/7/07, Jim Jewett <[EMAIL PROTECTED]> wrote:
> > A Signature object has the following structure attributes:
>
> > * name : str
> >     Name of the function.  This is not fully qualified because
> >     function objects for methods do not know the class they are
> >     contained within.  This makes functions and methods
> >     indistinguishable from one another when passed to decorators,
> >     preventing proper creation of a fully qualified name.
>
> (1)  Would this change with the new static __class__ attribute used
> for the new super?
>

I don't know enough about the super implementation to know.  If you
can figure out the class from the function object alone then sure,
this can change.

> (2)  What about functions without a name?  Do you want to say str or
> NoneType, or is that assumed?
>

What functions don't have a name?  Even lambdas have the name '<lambda>'.

> (3)  Is the Signature object live or frozen?  (name is writable ...
> will the Signature object reflect the new name, or the name in use at
> the time it was created?)
>

They are currently one-time creation objects.  One could change it to
use properties and do the look up dynamically by caching the function
object.  But I currently have it implemented as all created in
__init__ and then just left alone.

> > * var_annotations: dict(str, object)
> >     Dict that contains the annotations for the variable parameters.
> >     The keys are of the variable parameter with values of the
>
> Is there a special key for the "->" returns annotation, or is that
> available as a separate property?
>

Oops, that didn't get into the PEP for some reason.  The Signature
object has ``has_annotation``/``annotation`` attributes for the
'return' annotation.


> > The structure of the Parameter object is:
>
> > * name : (str | tuple(str))
> >     The name of the parameter as a string if it is not a tuple.  If
> >     the argument is a tuple then a tuple of strings is used.
>
> What is used for unnamed arguments (typically provide by C)?  I like
> None, but I see the arguments for both "" and missing attribute.
>

It's open for debate.  I didn't even think about functions not having
__name__ set.  Basically whatever people want to go with for var_args
and var_kw_args.

> > * position : int
> >     The position of the parameter within the signature of the
> >     function (zero-indexed).  For keyword-only parameters the position
> >     value is arbitrary while not conflicting with positional
> >     parameters.
>
> Is this just a property/alias for signature.parameters.index(self) ?
>

Assuming that 'self' refers to some parameter, yes.

> What should a "parameter" object not associated with a specific
> signature return?  -1, None, or missing attribute?
>

This is not an option as it must be specified by the Parameter
constructor.  A Parameter object should not exist without belonging to
a Signature object.  That's why neither Signature nor Parameter have
their constructors specified; the signature() function is the only way
you should cause the construction of either object.

> Is there a way to get the associated Signature, or is it "compiled
> out" when the Signature and its child Parameters are first
> constructed?  (I think the position property is the only attribute
> that would use it, unless you want some of the other attributes --
> like annotations -- to be live.)

There is currently no way to work backwards from a Parameter object to
its parent Signature.  It could be added if people wanted.

>
> ...
>
> I would also like to see a
>
>  * value : object
>
> attribute; this would be missing on most functions, but might be
> filled in on a Signature representing a closure, or an execution
> frame.

What for?  How does either have bearing on the call signature of a function?

>
>
> > When to construct the Signature object?
> > ---------------------------------------
>
> > The Signature object can either be created in an eager or lazy
> > fashion.  In the eager situation, the object can be created during
> > creation of the function object.
>
> Since most code doesn't need it, I would expect it to be optimized out
> at least as often as docstrings are.
>
> >  In the lazy situation, one would
> > pass a function object to a function and that would generate the
> > Signature object and store it to ``__signature__`` if
> > needed, and then return the value of ``__signature__``.
>
> Why store it?  Do you expect many use cases to need the signature more
> than once (but not to save it themselves)?

Because you can use these with decorators to allow introspection redirection::

 def dec(fxn):
   def inner(*args, **kwargs):
       return fxn(*args, **kwargs)
   sig = signature(fxn)
   inner.__signature__ = sig
   return inner

>
> If there is a __signature__ attribute on a object, you have to specify
> whether it can be replaced,

It can.

> which parts of it are writable,

Any of it.

> how that
> will affect the function's own behavior, etc.

It won't.

>  I also suspect it might
> become a source of heisenbugs, like the "reference leaks" that were
> really DUMMY items in a dict.
>
> If the Signature is just a snapshot no longer attached to the original
> function, then people won't expect changes to the Signature to affect
> the callable.
>

They are just snapshots unless people really want them to be live for
some reason.

> > Should ``Signature.bind`` return Parameter objects as keys?
>
> (see above) If a Signature is a snapshot (rather than a live part of
> the function), then it might make more sense to just add a value
> attribute to Parameter objects.
>

Why?  You might make several calls to bind() and thus setting what a
Parameter object would be bound to should be considered a temporary
thing.

> > Provide a mapping of parameter name to Parameter object?
> > --------------------------------------------------------
>
> > While providing access to the parameters in order is handy, it might
> > also be beneficial to provide a way to retrieve Parameter objects from
> > a Signature object based on the parameter's name.  Which style of
> > access (sequential/iteration or mapping) will influence how the
> > parameters are stored internally and whether __getitem__ accepts
> > strings or integers.
>
> I think it should accept both.
>
> What storage mechanism to use is an internal detail that should be
> left to the implementation.  I wouldn't expect Signature inspection to
> be inside a tight loop anyhow, unless it were part of a Generic
> Function dispatch engine ... and those authors (just PJE?) can
> optimize on what they actually need.
>

I guess I can just try to do ``item.__index__()`` and if that triggers
an AttributeError assume it is a name.

> > Remove ``has_*`` attributes?
> > ----------------------------
>
> > If an EAFP approach to the API is taken,
>
> Please leave them; it is difficult to catch Exceptions in a list 
> comprehension.
>

You can also just use hasattr() if needed.

> > Have ``var_args`` and ``_var_kw_args`` default to ``None``?
>
> Makes sense to me, particularly since it should probably be consistent
> with function name, and that should probably be None.

So another vote for None.

Thanks for the feedback, Jim!
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to