diff options
author | Andrew Svetlov <andrew.svetlov@gmail.com> | 2012-08-13 14:10:28 (GMT) |
---|---|---|
committer | Andrew Svetlov <andrew.svetlov@gmail.com> | 2012-08-13 14:10:28 (GMT) |
commit | 4e48bf929b9d43afcd6567d69a4b384959775ca9 (patch) | |
tree | 72be4dbb60ea1ce16cbdbed6290a113ed0e54509 | |
parent | 4e9e9c1c44309c90d167ab1e2a3e85582f1a52f8 (diff) | |
download | cpython-4e48bf929b9d43afcd6567d69a4b384959775ca9.zip cpython-4e48bf929b9d43afcd6567d69a4b384959775ca9.tar.gz cpython-4e48bf929b9d43afcd6567d69a4b384959775ca9.tar.bz2 |
Issue #15151: PEP 362 — document signature and related classes for inspect.py
Initial patch by Yury Selivanov
-rw-r--r-- | Doc/library/inspect.rst | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 3ec17d6..e5010c8 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -395,6 +395,267 @@ Retrieving source code onwards is removed. Also, all tabs are expanded to spaces. +.. _inspect-signature-object: + +Introspecting callables with Signature Object +--------------------------------------------- + +Signature object represents the call signature of a callable object and its +return annotation. To get a Signature object use the :func:`signature` +function. + + +.. versionadded:: 3.3 + +.. seealso:: + + :pep:`362` - Function Signature Object. + The detailed specification, implementation details and examples. + + +.. function:: signature(callable) + + Returns a :class:`Signature` object for the given ``callable``:: + + >>> from inspect import signature + >>> def foo(a, *, b:int, **kwargs): + ... pass + + >>> sig = signature(foo) + + >>> str(sig) + '(a, *, b:int, **kwargs)' + + >>> str(sig.parameters['b']) + 'b:int' + + >>> sig.parameters['b'].annotation + <class 'int'> + + Accepts a wide range of python callables, from plain functions and classes + to :func:`functools.partial` objects. + + .. note:: + + Some callables may not be introspectable in certain implementations + of Python. For example, in CPython, built-in functions defined in C + provide no metadata about their arguments. + + +.. class:: Signature + + A Signature object represents the call signature of a function and its + return annotation. For each parameter accepted by the function it + stores a :class:`Parameter` object in its :attr:`parameters` collection. + + Signature objects are *immutable*. Use :meth:`Signature.replace` to make + a modified copy. + + .. attribute:: Signature.empty + + A special class-level marker to specify absence of a return annotation. + + .. attribute:: Signature.parameters + + An ordered mapping of parameters' names to the corresponding + :class:`Parameter` objects. + + .. attribute:: Signature.return_annotation + + The "return" annotation for the callable. If the callable has + no "return" annotation, this attribute is set to + :attr:`Signature.empty`. + + .. method:: Signature.bind(*args, **kwargs) + + Creates a mapping from positional and keyword arguments to parameters. + Returns :class:`BoundArguments` if ``*args`` and ``**kwargs`` match + the signature, or raises a :exc:`TypeError`. + + .. method:: Signature.bind_partial(*args, **kwargs) + + Works the same way as :meth:`Signature.bind`, but allows the + omission of some required arguments (mimics :func:`functools.partial` + behavior.) Returns :class:`BoundArguments`, or raises a :exc:`TypeError` + if the passed arguments do not match the signature. + + .. method:: Signature.replace([parameters], *, [return_annotation]) + + Creates a new Signature instance based on the instance replace was + invoked on. It is possible to pass different ``parameters`` and/or + ``return_annotation`` to override the corresponding properties of + the base signature. To remove return_annotation from the copied + Signature, pass in :attr:`Signature.empty`. + + :: + + >>> def test(a, b): + ... pass + >>> sig = signature(test) + >>> new_sig = sig.replace(return_annotation="new return anno") + >>> str(new_sig) + "(a, b) -> 'new return anno'" + + + +.. class:: Parameter + + Parameter objects are *immutable*. Instead of modifying a Parameter object, + you can use :meth:`Parameter.replace` to create a modified copy. + + .. attribute:: Parameter.empty + + A special class-level marker to specify absence of default + values and annotations. + + .. attribute:: Parameter.name + + The name of the parameter as a string. Must be a valid python identifier + name (with the exception of ``POSITIONAL_ONLY`` parameters, which can + have it set to ``None``.) + + .. attribute:: Parameter.default + + The default value for the parameter. If the parameter has no default + value, this attribute is set to :attr:`Parameter.empty`. + + .. attribute:: Parameter.annotation + + The annotation for the parameter. If the parameter has no annotation, + this attribute is set to :attr:`Parameter.empty`. + + .. attribute:: Parameter.kind + + Describes how argument values are bound to the parameter. + Possible values (accessible via :class:`Parameter`, like + ``Parameter.KEYWORD_ONLY``): + + +------------------------+----------------------------------------------+ + | Name | Meaning | + +========================+==============================================+ + | *POSITIONAL_ONLY* | Value must be supplied as a positional | + | | argument. | + | | | + | | Python has no explicit syntax for defining | + | | positional-only parameters, but many built-in| + | | and extension module functions (especially | + | | those that accept only one or two parameters)| + | | accept them. | + +------------------------+----------------------------------------------+ + | *POSITIONAL_OR_KEYWORD*| Value may be supplied as either a keyword or | + | | positional argument (this is the standard | + | | binding behaviour for functions implemented | + | | in Python.) | + +------------------------+----------------------------------------------+ + | *VAR_POSITIONAL* | A tuple of positional arguments that aren't | + | | bound to any other parameter. This | + | | corresponds to a ``*args`` parameter in a | + | | Python function definition. | + +------------------------+----------------------------------------------+ + | *KEYWORD_ONLY* | Value must be supplied as a keyword argument.| + | | Keyword only parameters are those which | + | | appear after a ``*`` or ``*args`` entry in a | + | | Python function definition. | + +------------------------+----------------------------------------------+ + | *VAR_KEYWORD* | A dict of keyword arguments that aren't bound| + | | to any other parameter. This corresponds to a| + | | ``**kwargs`` parameter in a Python function | + | | definition. | + +------------------------+----------------------------------------------+ + + Print all keyword-only arguments without default values:: + + >>> def foo(a, b, *, c, d=10): + ... pass + + >>> sig = signature(foo) + >>> for param in sig.parameters.values(): + ... if (param.kind == param.KEYWORD_ONLY and + ... param.default is param.empty): + ... print('Parameter:', param) + Parameter: c + + .. method:: Parameter.replace(*, [name], [kind], [default], [annotation]) + + Creates a new Parameter instance based on the instance replaced was + invoked on. To override a :class:`Parameter` attribute, pass the + corresponding argument. To remove a default value or/and an annotation + from a Parameter, pass :attr:`Parameter.empty`. + + :: + + >>> from inspect import Parameter + >>> param = Parameter('foo', Parameter.KEYWORD_ONLY, default=42) + >>> str(param) + 'foo=42' + + >>> str(param.replace()) # Will create a shallow copy of 'param' + 'foo=42' + + >>> str(param.replace(default=Parameter.empty, annotation='spam')) + "foo:'spam'" + + +.. class:: BoundArguments + + Result of a :meth:`Signature.bind` or :meth:`Signature.bind_partial` call. + Holds the mapping of arguments to the function's parameters. + + .. attribute:: BoundArguments.arguments + + An ordered, mutable mapping (:class:`collections.OrderedDict`) of + parameters' names to arguments' values. Contains only explicitly + bound arguments. Changes in :attr:`arguments` will reflect in + :attr:`args` and :attr:`kwargs`. + + Should be used in conjunction with :attr:`Signature.parameters` for + any arguments processing purposes. + + .. note:: + + Arguments for which :meth:`Signature.bind` or + :meth:`Signature.bind_partial` relied on a default value are skipped. + However, if needed, it's easy to include them + + :: + + >>> def foo(a, b=10): + ... pass + + >>> sig = signature(foo) + >>> ba = sig.bind(5) + + >>> ba.args, ba.kwargs + ((5,), {}) + + >>> for param in sig.parameters.values(): + ... if param.name not in ba.arguments: + ... ba.arguments[param.name] = param.default + + >>> ba.args, ba.kwargs + ((5, 10), {}) + + + .. attribute:: BoundArguments.args + + Tuple of positional arguments values. Dynamically computed + from the :attr:`arguments` attribute. + + .. attribute:: BoundArguments.kwargs + + Dict of keyword arguments values. Dynamically computed + from the :attr:`arguments` attribute. + + :attr:`args` and :attr:`kwargs` properties can be used to invoke functions:: + + def test(a, *, b): + ... + + sig = signature(test) + ba = sig.bind(10, b=20) + test(*ba.args, **ba.kwargs) + + .. _inspect-classes-functions: Classes and functions @@ -443,6 +704,10 @@ Classes and functions The first four items in the tuple correspond to :func:`getargspec`. + .. note:: + Consider using the new :ref:`Signature Object <inspect-signature-object>` + interface, which provides a better way of introspecting functions. + .. function:: getargvalues(frame) @@ -505,6 +770,9 @@ Classes and functions .. versionadded:: 3.2 + .. note:: + Consider using the new :meth:`Signature.bind` instead. + .. function:: getclosurevars(func) |