Skip to content

Commit 534c911

Browse files
pkchgvanrossum
authored andcommitted
Update generic class attribute and type variable usage (#239)
See python/mypy#2878
1 parent ff3b268 commit 534c911

File tree

1 file changed

+35
-14
lines changed

1 file changed

+35
-14
lines changed

pep-0484.txt

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ elements. Example::
288288

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

291-
Generics can be parametrized by using a new factory available in
291+
Generics can be parameterized by using a new factory available in
292292
``typing`` called ``TypeVar``. Example::
293293

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

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

314315
from typing import TypeVar
315316

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

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

615+
Using generic classes (parameterized or not) to access attributes will result
616+
in type check failure. Outside the class definition body, a class attribute
617+
cannot be assigned, and can only be looked up by accessing it through the
618+
class instance that does not have same-named instance attribute::
619+
620+
# (continued from previous example)
621+
Node[int].x = 1 # Error
622+
Node[int].x # Error
623+
Node.x = 1 # Error
624+
Node.x # Error
625+
type(p).x # Error
626+
p.x # Ok (evaluates to None)
627+
Node[int]().x # Ok (evaluates to None)
628+
p.x = 1 # Ok, but assigning to instance attribute
629+
613630
Generic versions of abstract collections like ``Mapping`` or ``Sequence``
614631
and generic versions of built-in classes -- ``List``, ``Dict``, ``Set``,
615632
and ``FrozenSet`` -- cannot be instantiated. However, concrete user-defined
@@ -701,11 +718,11 @@ classes without a metaclass conflict.
701718
Type variables with an upper bound
702719
----------------------------------
703720

704-
A type variable may specify an upper bound using ``bound=<type>``.
705-
This means that an actual type substituted (explicitly or implicitly)
706-
for the type variable must be a subtype of the boundary type. A
707-
common example is the definition of a Comparable type that works well
708-
enough to catch the most common errors::
721+
A type variable may specify an upper bound using ``bound=<type>`` (note:
722+
<type> itself cannot be parametrized by type variables). This means that an
723+
actual type substituted (explicitly or implicitly) for the type variable must
724+
be a subtype of the boundary type. A common example is the definition of a
725+
``Comparable`` type that works well enough to catch the most common errors::
709726

710727
from typing import TypeVar
711728

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

1189-
``Type[Any]`` is also supported (see below for its meaning). However,
1190-
other special constructs like ``Tuple`` or ``Callable`` are not
1191-
allowed.
1206+
``Type[Any]`` is also supported (see below for its meaning).
1207+
1208+
``Type[T]`` where ``T`` is a type variable is allowed when annotating the
1209+
first argument of a class method (see the relevant section).
1210+
1211+
Any other special constructs like ``Tuple`` or ``Callable`` are not allowed
1212+
as an argument to ``Type``.
11921213

11931214
There are some concerns with this feature: for example when
11941215
``new_user()`` calls ``user_class()`` this implies that all subclasses
@@ -2442,7 +2463,7 @@ Copyright
24422463
This document has been placed in the public domain.
24432464

24442465

2445-
2466+
24462467
..
24472468
Local Variables:
24482469
mode: indented-text

0 commit comments

Comments
 (0)