Steven D'Aprano wrote:
Brett Cannon wrote:
PEP: 362
Title: Function Signature Object
Version: $Revision$
Last-Modified: $Date$
Author: Brett Cannon <br...@python.org>, Jiwon Seo <seoji...@gmail.com>,
Yury Selivanov <yseliva...@sprymix.com>, Larry Hastings <
la...@hastings.org>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 21-Aug-2006
Python-Version: 3.3
Post-History: 04-Jun-2012
Abstract
========
Python has always supported powerful introspection capabilities,
including introspecting functions and methods. (For the rest of
this PEP, "function" refers to both functions and methods). By
examining a function object you can fully reconstruct the function's
signature. Unfortunately this information is stored in an inconvenient
manner, and is spread across a half-dozen deeply nested attributes.
This PEP proposes a new representation for function signatures.
The new representation contains all necessary information about a
function
and its parameters, and makes introspection easy and straightforward.
It's already easy and straightforward, thanks to the existing
inspect.getfullargspec function. If this existing inspect function is
lacking something, the PEP should explain what, and why the inspect
function can't be fixed.
However, this object does not replace the existing function
metadata, which is used by Python itself to execute those
functions. The new metadata object is intended solely to make
function introspection easier for Python programmers.
What happens when the existing function metadata and the __signature__
object disagree?
Are there use-cases where we want them to disagree, or is disagreement
always a sign that something is broken?
Signature Object
================
A Signature object represents the overall signature of a function.
It stores a `Parameter object`_ for each parameter accepted by the
function, as well as information specific to the function itself.
There's a considerable amount of data recorded, including a number of
mappings (dicts?). This potentially increase the size of functions, and
the overhead of creating them. Since most functions are never
introspected, or only rarely introspected, it seems rather wasteful to
record all this data "just in case", particularly since it's already
recorded once in the function metadata and/or code object.
I agree with Stephen. Don't forget that each list comprehension
evaluation involves creating a temporary function object.
A Signature object has the following public attributes and methods:
* name : str
Name of the function.
Functions already record their name (twice!), and it is simple enough to
query func.__name__. What reason is there for recording it a third time,
in the Signature object?
Besides, I don't consider the name of the function part of the
function's signature. Functions can have multiple names, or no name at
all, and the calling signature remains the same.
Even if we limit the discussion to distinct functions (rather than a
single function with multiple names), I consider spam(x, y, z) ham(x, y,
z) and eggs(x, y, z) to have the same signature. Otherwise, it makes it
difficult to talk about one function having the same signature as
another function, unless they also have the same name. Which would be
unfortunate.
* qualname : str
Fully qualified name of the function.
What's the fully qualified name of the function, and why is it needed?
[...]
The structure of the Parameter object is:
* is_args : bool
True if the parameter accepts variable number of arguments
(``\*args``-like), else False.
"args" is just a common name for the parameter, not for the kind of
parameter. *args (or *data, *whatever) is a varargs parameter, and so
the attribute should be called "is_varargs".
* is_kwargs : bool
True if the parameter accepts variable number of keyword
arguments (``\*\*kwargs``-like), else False.
Likewise for **kwargs (or **kw, etc.) I'm not sure if there is a common
convention for keyword varargs, so I see two options:
is_varkwargs
is_kwvarargs
* is_implemented : bool
True if the parameter is implemented for use. Some platforms
implement functions but can't support specific parameters
(e.g. "mode" for os.mkdir). Passing in an unimplemented
parameter may result in the parameter being ignored,
or in NotImplementedError being raised. It is intended that
all conditions where ``is_implemented`` may be False be
thoroughly documented.
What to do about parameters which are partly implemented? E.g.
mode='spam' is implemented but mode='ham' is not.
Is there a use-case for is_implemented?
[...]
Annotation Checker
def check_type(sig, arg_name, arg_type, arg_value):
# Internal function that incapsulates arguments type checking
/s/incapsulates/encapsulates
Open Issues
===========
inspect.getfullargspec is currently unable to introspect builtin
functions and methods. Should builtins gain a __signature__ so they can
be introspected?
I'm +0 on this, but care is needed as print and [].append are the same
type in CPython.
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. 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__``.
In the current implementation, signatures are created only on demand
("lazy").
+1
+1 also. See comment above about list comprehensions
Deprecate ``inspect.getfullargspec()`` and ``inspect.getcallargs()``?
---------------------------------------------------------------------
-1
Since the Signature object replicates the use of ``getfullargspec()``
and ``getcallargs()`` from the ``inspect`` module it might make sense
to begin deprecating them in 3.3.
I think it is way to soon to deprecate anything. I don't think we should
even consider PendingDeprecation until at least 3.4.
Actually, I would go further: leave getfullargspec to extract the
*actual* argument spec from the code object, and __signature__ to be the
claimed argument spec. Earlier, you state:
"Changes to the Signature object, or to any of its data members,
do not affect the function itself."
which leaves the possibility that __signature__ may no longer match the
actual argument spec, for some reason. If you remove getfullargspec,
people will have to reinvent it to deal with such cases.
_______________________________________________
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