8000 Various doc updates by gvanrossum · Pull Request #3314 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

Various doc updates #3314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 3, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Docs for flexible Callable
  • Loading branch information
Guido van Rossum committed May 3, 2017
commit 3148825b42da99d0ba98b827bd8d2991a501755c
124 changes: 124 additions & 0 deletions docs/source/kinds_of_types.rst
8000
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,130 @@ using bidirectional type inference:
If you want to give the argument or return value types explicitly, use
an ordinary, perhaps nested function definition.

Extended Callable types
***********************

As an experimental mypy extension, you can specify ``Callable`` types
that support keyword arguments, optional arguments, and more. The
"argument" part of the ``Callable`` specification (the part specifying
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where you specify the arguments of a Callable, you can choose to supply just the type of a nameless positional argument, or an "argument specifier" representing a more complicated form of argument.

the types of the arguments) can be a list of "argument specifiers"
instead of a list of types. This allows one to more closely emulate
the full range of possibilities given by the ``def`` statement in
Python.

As an example, here's a complicated function definition and the
corresponding ``Callable``:

.. code-block:: python

from typing import Callable
from mypy_extensions import (Arg, DefaultArg, NamedArg,
DefaultNamedArg, VarArg, KwArg)

def func(__a: int, # This convention is for nameless arguments
b: int,
c: int = 0,
*args: int,
d: int,
e: int = 0,
**kwargs: int) -> int:
...

F = Callable[[Arg(int), # No argument name given
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider making this just int, to show that a raw type has no arg name and that you can mix them?

Arg(int, 'b'),
DefaultArg(int, 'c'),
VarArg(int),
NamedArg(int, 'd'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably the wrong place for this discussion, but why don't we call this KeywordOnlyArg? NamedArg is confusing because normal args are also named.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That discussion can go in python/typing#264, which itself has a few naming differences from Naomi's PRs (#2426 and python/typeshed#684). Or it can go into Naomi's PEP once she's written it.

DefaultNamedArg(int, 'e'),
KwArg(int)],
int]

f: F = func

Argument specifiers are special function calls that can specify the
following aspects of an argument:

- its type (the only thing that the basic format supports)

- its name (if it has one)

- whether it may be omitted

- whether it may or must be passed using a keyword

- whether it is a ``*args`` argument (representing the remaining
positional arguments)

- whether it is a ``**kwargs`` argument (representing the remaining
keyword arguments)

The following functions are available in ``mypy_extensions`` for this
purpose:

.. code-block:: python

def Arg(type=Any, name=None):
# A normal, mandatory, positional argument.
# If the name is specified it may be passed as a keyword.

def DefaultArg(type=Any, name=None):
# An optional positional argument (i.e. with a default value).
# If the name is specified it may be passed as a keyword.

def NamedArg(type=Any, name=None):
# A mandatory keyword-only argument.

def DefaultNamedArg(type=Any, name=None):
# An optional keyword-only argument (i.e. with a default value).

def VarArg(type=Any):
# A *args-style variadic positional argument.
# A single VarArg() specifier represents all remaining
# positional arguments.

def KwArg(type=Any):
# A **kwargs-style variadic keyword argument.
# A single KwArg() specifier represents all remaining
# keyword arguments.

In all cases, the ``type`` argument defaults to ``Any``, and if the
``name`` argument is omitted the argument has no name (the name is
required for ``NamedArg`` and ``DefaultNamedArg``). A basic
``Callable`` such as

.. code-block:: python

MyFunc = Callable[[int, str, int], float]

is equivalent to the following:

.. code-block:: python

MyFunc = Callable[[Arg(int), Arg(str), Arg(int)], float]

A ``Callable`` with unspecified argument types, such as
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This equivalency is near, but not entirely true. A Callable[..., int] gets is_ellipsis_args set to True, unlike Callable[[VarArg(), KwArg()], int]. A Callable with ellipsis args is not only considered a subtype of all Callables with compatible return types (which it naturally is), but also a supertype of all Callables with compatible return types (which is weird and special). This is the only other wart in the type system I know of that's comparable to Any.


.. code-block:: python

MyOtherFunc = Callable[..., int]

is equivalent to

.. code-block:: python

MyOtherFunc = Callable[[VarArg(), KwArg()], int]

.. note::

This feature is experimental. Details of the implementation may
change and there may be unknown limitations. **IMPORTANT:** At
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the first "at runtime" and maybe make it "Each of the functions above currently returns its type argument..."

(to remove the awkwardly repeated phrase)

runtime, each of the functions above just returns its ``type``
argument, so the information contained in the argument specifiers
is not available at runtime. This limitation is necessary for
backwards compatibility with the existing ``typing.py`` module as
present in the Python 3.5+ standard library and distributed via
PyPI.

.. _union-types:

Union types
Expand Down
0