Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
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
66 changes: 36 additions & 30 deletions Doc/library/stdtypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4746,47 +4746,47 @@ single class dictionary lookup is negligible.
.. _types-union:

Union Type
====================
==========

.. index::
object: Union
pair: union; type

A union object holds the value of the ``|`` (bitwise or) operation on
multiple :ref:`type objects<bltin-type-objects>`. This enables cleaner type
hinting syntax compared to :data:`typing.Union`.
multiple :ref:`type objects<bltin-type-objects>`. These types are intended
primarily for type annotations. The union type expression enables cleaner
type hinting syntax compared to :data:`typing.Union`.

.. describe:: X | Y | ...

Defines a union object which holds types *X*, *Y*, and so forth. X | Y
means either X or Y. It is syntactically equivalent to
``typing.Union[X, Y, ...]``.
Defines a union object which holds types *X*, *Y*, and so forth. ``X | Y``
means either X or Y. It is equivalent to ``typing.Union[X, Y, ...]``.
Comment thread
Fidget-Spinner marked this conversation as resolved.
Resolved
Example::

def square(number: int | float) -> int | float:
return number ** 2

.. describe:: union_object == other

Union objects can be tested for equality with other union objects. Details:
Union objects can be tested for equality with other union objects. Details:

* Unions of unions are flattened, e.g.::

(int | str) | float == int | str | float

* Redundant arguments are skipped, e.g.::
* Redundant types are removed, e.g.::

int | str | int == int | str

* When comparing unions, the argument order is ignored, e.g.::
* When comparing unions, the order is ignored, e.g.::

int | str == str | int

* Compatible with :data:`typing.Union`::
* It is compatible with :data:`typing.Union`::

int | str == typing.Union[int, str]

* Optional values are equivalent to :data:`typing.Optional`::
* Optional types can be spelled as a union with ``None``::

str | None == typing.Optional[str]

Expand All @@ -4797,9 +4797,12 @@ hinting syntax compared to :data:`typing.Union`.
>>> isinstance("", int | str)
True

Union objects containing parametrized generics cannot be used::
However, union objects containing parameterized :ref:`generics<generics>`
cannot be used::

>>> isinstance(1, int | list[int])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: isinstance() argument 2 cannot contain a parameterized generic

.. describe:: issubclass(obj, union_object)
Expand All @@ -4809,42 +4812,45 @@ hinting syntax compared to :data:`typing.Union`.
>>> issubclass(bool, int | str)
True

Union objects containing parametrized generics cannot be used::
However, union objects containing parameterized :ref:`generics<generics>`
cannot be used::

>>> issubclass(bool, bool | list[str])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: issubclass() argument 2 cannot contain a parameterized generic


The type for the Union object is :data:`types.Union`. An object
cannot be instantiated from the type::
The type for the Union object is :data:`types.Union`. An object cannot be
instantiated from the type::

>>> import types
>>> isinstance(int | str, types.Union)
True
>>> types.Union()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'types.Union' instances

.. note::
The :meth:`__or__` method for type objects was added to support the syntax
X | Y. If a metaclass implements :meth:`__or__`, the Union may
``X | Y``. If a metaclass implements :meth:`__or__`, the Union may
override it::

class M(type):
def __or__(self, other):
return "Hello"

class C(metaclass=M):
pass

# 'Hello'
print(C | int)

# 'int | __main__.C'
print(int | C)
>>> class M(type):
... def __or__(self, other):
... return "Hello"
...
>>> class C(metaclass=M):
... pass
...
>>> C | int
'Hello'
>>> int | C
int | __main__.C

.. seealso::

:pep:`604` -- PEP proposing the Union object and type.
:pep:`604` -- PEP proposing the ``X | Y`` syntax and the Union type.

.. versionadded:: 3.10

Expand Down
2 changes: 1 addition & 1 deletion Doc/library/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ Standard names are defined for the following types:

.. data:: Union

The type of :ref:`builtins.Union<types-union>`.
The type of :ref:`union type expressions<types-union>`.

.. versionadded:: 3.10

Expand Down
4 changes: 2 additions & 2 deletions Doc/library/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -545,8 +545,8 @@ These can be used as types in annotations using ``[]``, each having a unique syn
Don't remove explicit subclasses from unions at runtime.

.. versionchanged:: 3.10
Unions can now be written as X | Y. See :ref:`builtins.Union
<types-union>`.
Unions can now be written as ``X | Y``. See
:ref:`union type expressions<types-union>`.

.. data:: Optional

Expand Down
25 changes: 22 additions & 3 deletions Doc/whatsnew/3.10.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,28 @@ New Features
* :pep:`618`: The :func:`zip` function now has an optional ``strict`` flag, used
to require that all the iterables have an equal length.

* :pep:`604`: Builtin Union type to allow writing X | Y in place of
``typing.Union[X, Y]``.
(Contributed by Maggie Moss and Philippe Prados in :issue:`41428`.)
PEP604: New Type Operator
-------------------------
Comment thread
Fidget-Spinner marked this conversation as resolved.
Resolved
A new type union operator was introduced which enables the syntax ``X | Y``.
This provides a cleaner way of expressing 'either type X or type Y' instead of
using :data:`typing.Union`.
Comment thread
Fidget-Spinner marked this conversation as resolved.
Resolved

In previous versions of Python, to apply a type hint for functions accepting
arguments of multiple types, :data:`typing.Union` was used::

def square(number: Union[int, float]) -> Union[int, float]:
return number ** 2


Now, type hints can be written in a more succinct manner::

def square(number: int | float) -> int | float:
return number ** 2


See :pep:`604` for more details.

(Contributed by Maggie Moss and Philippe Prados in :issue:`41428`.)

Other Language Changes
======================
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Add documentation for :pep:`604` (Allow writing union types as X | Y).
Add documentation for :pep:`604` (Allow writing union types as ``X | Y``).