8000 Describe type vars with co/contra variance. Fixes #2. · python/typing@5f110c7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5f110c7

Browse files
author
Guido van Rossum
committed
Describe type vars with co/contra variance. Fixes #2.
1 parent bc6276d commit 5f110c7

File tree

1 file changed

+89
-4
lines changed

1 file changed

+89
-4
lines changed

pep-0484.txt

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,8 @@ for the type variable must be a subclass of the boundary type. A
466466
common example is the definition of a Comparable type that works well
467467
enough to catch the most common errors::
468468

469+
from typing import TypeVar
470+
469471
class Comparable(metaclass=ABCMeta):
470472
@abstractmethod
471473
def __lt__(self, other: Any) -> bool: ...
@@ -495,6 +497,83 @@ upper bound just requires that the actual type is a subclass of the
495497
boundary type.
496498

497499

500+
Covariance and contravariance
501+
-----------------------------
502+
503+
Consider a class ``Employee`` with a subclass ``Manager``. Now
504+
suppose we have a function with an argument annotated with
505+
``List[Employee]``. Should we be allowed to call this function with a
506+
variable of type ``List[Manager]`` as its argument? Many people would
507+
answer "yes, of course" without even considering the consequences.
508+
But unless we know more about the function, a type checker should
509+
reject such a call: the function might append an ``Employee`` instance
510+
to the list, which would violate the variable's type in the caller.
511+
512+
It turns out such an argument acts _contravariantly_, whereas the
513+
intuitive answer (which is correct in case the function doesn't mutate
514+
its argument!) requires the argument to act _covariantly_. A longer
515+
introduction to these concepts can be found on Wikipedia
516+
[wiki-variance]_; here we just show how to control a type checker's
517+
behavior.
518+
519+
By default type variables are considered _invariant_, which means that
520+
arguments for arguments annotated with types like ``List[Employee]``
521+
must exactly match the type annotation -- no subclasses or
522+
superclasses of the type parameter (in this example ``Employee``) are
523+
allowed.
524+
525+
To facilitate the declaration of container types where covariant type
526+
checking is acceptable, a type variable can be declared using
527+
``covariant=True``. For the (rare) case where contravariant behavior
528+
is desirable, pass ``contravariant=True``. At most one of these may
529+
be passed.
530+
531+
A typical example involves defining an immutable container class::
532+
533+
from typing import TypeVar
534+
535+
T = TypeVar('T', covariant=True)
536+
537+
class ImmutableList(Generic[T]):
538+
def append(self, T): ...
539+
...
540+
541+
class Employee: ...
542+
543+
class Manager(Employee): ...
544+
545+
def dump_employees(emps: ImmutableList[Employee]) -> None: ...
546+
547+
mgrs = ... # type: ImmutableList[Mananger]
548+
mgrs.append(Manager())
549+
550+
dump_employees(mgrs) # OK
551+
552+
The immutable collection classes in ``typing`` are all defined using a
553+
covariant type variable (e.g. ``Mapping`` and ``Sequence``). The
554+
mutable collection classes (e.g. ``MutableMapping`` and
555+
``MutableSequence``) are defined using regular invariant type
556+
variables. The one example of a contravariant type variable is the
557+
``Generator`` type, which is contravariant in the ``send()`` argument
558+
type (see below).
559+
560+
Note: variance affects type parameters for generic types -- it does
561+
not affect regular parameters. For example, the following example is
562+
fine::
563+
564+
from typing import TypeVar
565+
566+
class Employee: ...
567+
568+
class Manager(Employee): ...
569+
570+
E = TypeVar('E', bound=Employee) # Invariant
571+
572+
def dump_employee(e: E) -> None: ...
573+
574+
dump_employee(Manager()) # OK
575+
576+
498577
The numeric tower
499578
-----------------
500579

@@ -1039,7 +1118,10 @@ the abstract collection types defined below, e.g. ``Mapping``,
10391118
The ``typing`` module defines the ``Generator`` type for return values
10401119
of generator functions. It is a subtype of ``Iterable`` and it has
10411120
additional type variables for the type accepted by the ``send()``
1042-
method and the return type of the generator:
1121+
method (which is contravariant -- a generator that accepts sending it
1122+
``Employee`` instance is valid in a context where a generator is
1123+
required that accepts sending it ``Manager`` instances) and the return
1124+
type of the generator:
10431125

10441126
* Generator, used as ``Generator[yield_type, send_type, return_type]``
10451127

@@ -1437,6 +1519,12 @@ References
14371519
.. [mypy]
14381520
http://mypy-lang.org
14391521

1522+
.. [gvr-artima]
1523+
http://www.artima.com/weblogs/viewpost.jsp?thread=85551
1524+
1525+
.. [wiki-variance]
1526+
http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29
1527+
14401528
.. [typeshed]
14411529
https://github.com/JukkaL/typeshed/
14421530

@@ -1446,9 +1534,6 @@ References
14461534
.. [pylint]
14471535
http://www.pylint.org
14481536

1449-
.. [gvr-artima]
1450-
http://www.artima.com/weblogs/viewpost.jsp?thread=85551
1451-
14521537
.. [roberge]
14531538
http://aroberge.blogspot.com/2015/01/type-hinting-in-python-focus-on.html
14541539

0 commit comments

Comments
 (0)
0