Skip to content

Update generic class attribute and type variable usage #239

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 11, 2017
Merged
Changes from all 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
49 changes: 35 additions & 14 deletions pep-0484.txt
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ elements. Example::

def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...

Generics can be parametrized by using a new factory available in
Generics can be parameterized by using a new factory available in
``typing`` called ``TypeVar``. Example::

from typing import Sequence, TypeVar
Expand All @@ -306,10 +306,11 @@ variable (it should not be used as part of a larger expression). The
argument to ``TypeVar()`` must be a string equal to the variable name
to which it is assigned. Type variables must not be redefined.

``TypeVar`` supports constraining parametric types to a fixed set of
possible types. For example, we can define a type variable that ranges
over just ``str`` and ``bytes``. By default, a type variable ranges
over all possible types. Example of constraining a type variable::
``TypeVar`` supports constraining parametric types to a fixed set of possible
types (note: those types cannot be parametrized by type variables). For
example, we can define a type variable that ranges over just ``str`` and
``bytes``. By default, a type variable ranges over all possible types.
Example of constraining a type variable::

from typing import TypeVar

Expand Down Expand Up @@ -583,6 +584,7 @@ argument(s) is substituted. Otherwise, ``Any`` is assumed. Example::
class Node(Generic[T]):
def __init__(self, label: T = None) -> None:
...
x = None # Type: T

x = Node('') # Inferred type is Node[str]
y = Node(0) # Inferred type is Node[int]
Expand Down Expand Up @@ -610,6 +612,21 @@ the runtime class of the objects created by instantiating them doesn't
record the distinction. This behavior is called "type erasure"; it is
common practice in languages with generics (e.g. Java, TypeScript).

Using generic classes (parameterized or not) to access attributes will result
in type check failure. Outside the class definition body, a class attribute
cannot be assigned, and can only be looked up by accessing it through the
class instance that does not have same-named instance attribute::

# (continued from previous example)
Node[int].x = 1 # Error
Node[int].x # Error
Node.x = 1 # Error
Node.x # Error
type(p).x # Error
p.x # Ok (evaluates to None)
Node[int]().x # Ok (evaluates to None)
p.x = 1 # Ok, but assigning to instance attribute

Generic versions of abstract collections like ``Mapping`` or ``Sequence``
and generic versions of built-in classes -- ``List``, ``Dict``, ``Set``,
and ``FrozenSet`` -- cannot be instantiated. However, concrete user-defined
Expand Down Expand Up @@ -701,11 +718,11 @@ classes without a metaclass conflict.
Type variables with an upper bound
----------------------------------

A type variable may specify an upper bound using ``bound=<type>``.
This means that an actual type substituted (explicitly or implicitly)
for the type variable must be a subtype of the boundary type. A
common example is the definition of a Comparable type that works well
enough to catch the most common errors::
A type variable may specify an upper bound using ``bound=<type>`` (note:
<type> itself cannot be parametrized by type variables). This means that an
actual type substituted (explicitly or implicitly) for the type variable must
be a subtype of the boundary type. A common example is the definition of a
``Comparable`` type that works well enough to catch the most common errors::

from typing import TypeVar

Expand Down Expand Up @@ -1186,9 +1203,13 @@ concrete class object, e.g. in the above example::
new_non_team_user(ProUser) # OK
new_non_team_user(TeamUser) # Disallowed by type checker

``Type[Any]`` is also supported (see below for its meaning). However,
other special constructs like ``Tuple`` or ``Callable`` are not
allowed.
``Type[Any]`` is also supported (see below for its meaning).

``Type[T]`` where ``T`` is a type variable is allowed when annotating the
first argument of a class method (see the relevant section).

Any other special constructs like ``Tuple`` or ``Callable`` are not allowed
as an argument to ``Type``.

There are some concerns with this feature: for example when
``new_user()`` calls ``user_class()`` this implies that all subclasses
Expand Down Expand Up @@ -2439,7 +2460,7 @@ Copyright
This document has been placed in the public domain.



..
Local Variables:
mode: indented-text
Expand Down