159 lines
5.5 KiB
ReStructuredText
159 lines
5.5 KiB
ReStructuredText
|
PEP: 645
|
|||
|
Title: Allow writing optional types as ``x?``
|
|||
|
Author: Maggie Moss <maggiebmoss@gmail.com>
|
|||
|
Sponsor: Guido van Rossum <guido@python.org>
|
|||
|
Status: Draft
|
|||
|
Type: Process
|
|||
|
Content-Type: text/x-rst
|
|||
|
Created: 25-Aug-2020
|
|||
|
|
|||
|
|
|||
|
Abstract
|
|||
|
========
|
|||
|
This PEP proposes adding a ``?`` operator for types to allow writing ``int?`` in place of ``Optional[int]``.
|
|||
|
|
|||
|
|
|||
|
Motivation
|
|||
|
==========
|
|||
|
Types have become a valuable and powerful part of the Python language. However, many type annotations are verbose and add
|
|||
|
considerable friction to using type annotations. By improving the typing syntax, adding types to Python code becomes simpler
|
|||
|
and improves the development experience for Python users.
|
|||
|
|
|||
|
In a similar vein, a PEP to introduce short hand syntax for `Union types <https://www.python.org/dev/peps/pep-0604/>`_ [1]_ has
|
|||
|
been approved and implemented.
|
|||
|
|
|||
|
|
|||
|
Rationale
|
|||
|
=========
|
|||
|
|
|||
|
Types in Python can be quite verbose, this can be a hindrance when working towards type adoption. Making types more ergonomic,
|
|||
|
as was done with the Union type in PEP 604 (e.g., int | str), would reduce the effort needed to add types to new and existing Python code.
|
|||
|
The Optional annotation is used frequently in both partially and fully typed Python code bases. In a small sampling of `5 well-typed open
|
|||
|
source projects, on average 7% of annotations
|
|||
|
<https://gist.github.com/MaggieMoss/fd8dfe002b2702fae243dbf81a62624e>`_ [2] included at least one optional type. This indicates
|
|||
|
that updating the syntax has the potential to make types more concise, reduce code length and improve readability.
|
|||
|
|
|||
|
Simplifying the syntax for optionals has been `discussed previously <https://github.com/python/typing/issues/429>`_ [3] within the typing community.
|
|||
|
The consensus during these conversations has been that ``?`` is the preferred operator. There is no native support for unary ``?`` in Python and this will
|
|||
|
need to be added to the runtime.
|
|||
|
|
|||
|
Adding the ? sigil to the Python grammar has been proposed previously in `PEP 505 <https://www.python.org/dev/peps/pep-0505/>`_ [4], which is currently in a deferred state.
|
|||
|
PEP 505 proposes a:
|
|||
|
|
|||
|
- "None coalescing" binary operator ``??``
|
|||
|
|
|||
|
- "None-aware attribute access" operator ``?.`` ("maybe dot")
|
|||
|
|
|||
|
- "None-aware indexing" operator ``?[]`` ("maybe subscript")
|
|||
|
|
|||
|
|
|||
|
Should PEP 505 be approved in the future, it would not interfere with the typing specific ``?`` proposed in this PEP. As well,
|
|||
|
since all uses of the ``?`` would be conceptually related, it would not be confusing in terms of learning Python or a hindrance to quick visual comprehension.
|
|||
|
|
|||
|
The proposed syntax, with the postfix operator, mimics the optional syntax found in other typed languages, like C#, TypeScript and Swift.
|
|||
|
The widespread adoption and popularity of these languages means that Python developers are likely already familiar with this syntax.::
|
|||
|
|
|||
|
// Optional in Swift
|
|||
|
var example: String?
|
|||
|
|
|||
|
// Optional in C#
|
|||
|
string? example;
|
|||
|
|
|||
|
Adding this syntax would also follow the often used pattern of using builtin types as annotations. For example, `list`, `dict` and `None`. This would allow more annotations to be
|
|||
|
added to Python code without importing from `typing`.
|
|||
|
|
|||
|
|
|||
|
Specification
|
|||
|
=============
|
|||
|
|
|||
|
The new optional syntax should be accepted for function, variable, attribute and parameter annotations.
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
# instead of
|
|||
|
# def foo(x: Optional[int], y: Optional[str], z: Optional[list[int]): ...
|
|||
|
def foo(x: int?, y: str?, x: list[int]?): ...
|
|||
|
|
|||
|
# def bar(x: list[typing.Optional[int]]): ...
|
|||
|
def bar(x: list[int?]): ...
|
|||
|
|
|||
|
The new optional syntax should be equivalent to the existing typing.Optional syntax
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
typing.Optional[int] == int?
|
|||
|
|
|||
|
The new optional syntax should have the same identity as the existing typing.Optional syntax.
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
typing.Optional[int] is int?
|
|||
|
|
|||
|
|
|||
|
It should also be equivalent to a Union with None.
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
# old syntax
|
|||
|
int? == typing.Union[int, None]
|
|||
|
|
|||
|
# new syntax
|
|||
|
int? == int | None
|
|||
|
|
|||
|
Since the new Union syntax specified in PEP 604 is supported in ``isinstance`` and ``issubclass``, the new optional syntax should be supported in both ``isinstance`` and ``issubclass``,
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
isinstance(1, int?) # true
|
|||
|
issubclass(Child, Super?) # true
|
|||
|
|
|||
|
A new dunder method will need to be implemented to allow the `?` operator to be overloaded for other functionality.
|
|||
|
|
|||
|
|
|||
|
Backwards Compatibility
|
|||
|
=======================
|
|||
|
|
|||
|
``?`` is currently unused in Python syntax, therefore this PEP is fully backwards compatible.
|
|||
|
|
|||
|
Reference Implementation
|
|||
|
========================
|
|||
|
|
|||
|
A reference implementation can be found `here <https://github.com/python/cpython/compare/master...MaggieMoss:new-optional-syntax-postfix>`_ [5].
|
|||
|
|
|||
|
Rejected Ideas
|
|||
|
==============
|
|||
|
|
|||
|
Discussed alternatives were
|
|||
|
|
|||
|
* The ``~`` operator was considered in place of ``?``.
|
|||
|
* A prefix operator (``?int``).
|
|||
|
|
|||
|
|
|||
|
References
|
|||
|
==========
|
|||
|
|
|||
|
.. [1] PEP 604
|
|||
|
(https://www.python.org/dev/peps/pep-0604/)
|
|||
|
.. [2] Use of Optional Annotations in Open Source Python projects
|
|||
|
(https://gist.github.com/MaggieMoss/fd8dfe002b2702fae243dbf81a62624e)
|
|||
|
.. [3] Github Issue Discussion of Optional syntax
|
|||
|
(https://github.com/python/typing/issues/429)
|
|||
|
.. [4] PEP 505
|
|||
|
(https://www.python.org/dev/peps/pep-0505/)
|
|||
|
.. [5] Reference Implementation
|
|||
|
(https://github.com/python/cpython/compare/master...MaggieMoss:new-optional-syntax-postfix)
|
|||
|
|
|||
|
Copyright
|
|||
|
=========
|
|||
|
|
|||
|
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.
|
|||
|
|
|||
|
..
|
|||
|
Local Variables:
|
|||
|
mode: indented-text
|
|||
|
indent-tabs-mode: nil
|
|||
|
sentence-end-double-space: t
|
|||
|
fill-column: 70
|
|||
|
coding: utf-8
|
|||
|
End:
|