From d7aefb884c16b74ee4b4548ee3e06c40953f3e40 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 6 Apr 2015 19:54:09 -0700 Subject: [PATCH] Small edits; added Tuple[t, ...] and Callable[..., tr]. --- pep-0483.txt | 61 ++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/pep-0483.txt b/pep-0483.txt index c179f10e6..490ff9f9c 100644 --- a/pep-0483.txt +++ b/pep-0483.txt @@ -27,7 +27,7 @@ theory without which it is hard to discuss more detailed specifications. We start by explaining gradual typing; then we state some conventions and general rules; then we define the new special types (such as Union) that can be used in annotations; and finally we define the approach to -generic types. (The latter section needs more fleshing out; sorry!) +generic types. (TODO: The latter section needs more fleshing out; sorry!) Specification @@ -82,7 +82,7 @@ It's not okay to assign an Employee instance to a variable declared with type Manager: - m = Manager() # type: Manager -- m = Employee() # Fails static check +- m = Employee() # Fails static check However, suppose we have a variable whose type is **Any**: @@ -103,7 +103,7 @@ Notational conventions - t1, t2 etc. and u1, u2 etc. are types or classes. Sometimes we write ti or tj to refer to "any of t1, t2, etc." -- X, Y etc. are type variables (defined with Var(), see below). +- X, Y etc. are type variables (defined with TypeVar(), see below). - C, D etc. are classes defined with a class statement. - x, y etc. are objects or instances. - We use the terms type and class interchangeably, and we assume @@ -147,15 +147,15 @@ Types first is an int, the second a float; e.g., (42, 3.14). Tuple[u1, u2, ..., um] is a subclass of Tuple[t1, t2, ..., tn] if they have the same length (n==m) and each ui is a subclass of ti. To spell the type - of the empty tuple, use Tuple[()]. There is no way to define a - variadic tuple type. (TODO: Maybe Tuple[t1, ...] with literal - ellipsis?) + of the empty tuple, use Tuple[()]. A variadic homogeneous tuple type + can be written Tuple[t1, ...]. (That's three dots, a literal ellipsis; + and yes, that's a valid token in Python's syntax.) - **Callable[[t1, t2, ..., tn], tr]**. A function with positional argument types t1 etc., and return type tr. The argument list may be empty (n==0). There is no way to indicate optional or keyword - arguments, nor varargs (we don't need to spell those often enough to - complicate the syntax - however, Reticulated Python has a useful idea - here). This is covariant in the return type, but contravariant in the + arguments, nor varargs, but you can say the argument list is entirely + unchecked by writing Callable[..., tr] (again, a literal ellipsis). + This is covariant in the return type, but contravariant in the arguments. "Covariant" here means that for two callable types that differ only in the return type, the subclass relationship for the callable types follows that of the return types. (Example: @@ -197,33 +197,37 @@ are still controversial or not fully specified.) - Type aliases, e.g. - * point = Tuple[float, float] - * def distance(p: point) -> float: ... + * Point = Tuple[float, float] + * def distance(p: Point) -> float: ... - Forward references via strings, e.g. * class C: - + def compare(self, other: "C") -> int: ... + + def compare(self, other: 'C') -> int: ... -- If a default of None is specified, the type is implicitly optional, e.g. +- If a default of None is specified, the type is implicitly Optional, e.g. * def get(key: KT, default: VT = None) -> VT: ... - Don't use dynamic type expressions; use builtins and imported types only. No 'if'. - * def display(message: str if WINDOWS else bytes): # NOT OK + * def display(message: str if WINDOWS else bytes): # NOT OK - Type declaration in comments, e.g. - * x = [] # type: Sequence[int] + * x = [] # type: Sequence[int] - Type declarations using Undefined, e.g. * x = Undefined(str) -- Other things, e.g. casts, overloading and stub modules; best left to an +- Casts using cast(T, x), e.g. + + * x = cast(Any, frobozz()) + +- Other things, e.g. overloading and stub modules; best left to an actual PEP. @@ -233,25 +237,25 @@ Generic types (TODO: Explain more. See also the `mypy docs on generics `_.) -- **X = Var('X')**. Declares a unique type variable. The name must match +- **X = TypeVar('X')**. Declares a unique type variable. The name must match the variable name. -- **Y = Var('Y', t1, t2, ...).** Ditto, constrained to t1 etc. Behaves +- **Y = TypeVar('Y', t1, t2, ...).** Ditto, constrained to t1 etc. Behaves like Union[t1, t2, ...] for most purposes, but when used as a type variable, subclasses of t1 etc. are replaced by the most-derived base class among t1 etc. - Example of constrained type variables: - * AnyStr = Var('AnyStr', str, bytes) + * AnyStr = TypeVar('AnyStr', str, bytes) * def longest(a: AnyStr, b: AnyStr) -> AnyStr: - return a if len(a) >= len(b) else b - * x = longest('a', 'abc') # The inferred type for x is str + * x = longest('a', 'abc') # The inferred type for x is str - * y = longest('a', b'abc') # Fails static type check + * y = longest('a', b'abc') # Fails static type check * In this example, both arguments to longest() must have the same type (str or bytes), and moreover, even if the arguments are instances of a @@ -261,7 +265,7 @@ generics `_.) - For comparison, if the type variable was unconstrained, the common subclass would be chosen as the return type, e.g.: - * S = Var('S') + * S = TypeVar('S') * def longest(a: S, b: S) -> S: @@ -297,20 +301,17 @@ generics `_.) Think about co\*variance. No gimmicks like deriving from Sequence[Union[int, str]] or Sequence[Union[int, X]]. -- **Protocol**. Similar to Generic but uses structural equivalence. (TODO: - Explain, and think about co\*variance.) - Predefined generic types and Protocols in typing.py --------------------------------------------------- -(See also the `mypy typing.py -module `_.) +(See also the `typing.py module +`_.) - Everything from collections.abc (but Set renamed to AbstractSet). -- Dict, List, Set, a few more. (FrozenSet?) -- Pattern, Match. (Why?) -- IO, TextIO, BinaryIO. (Why?) +- Dict, List, Set, FrozenSet, a few more. +- re.Pattern[AnyStr], re.Match[AnyStr]. +- re.IO[AnyStr], re.TextIO ~ re.IO[str], re.BinaryIO ~ re.IO[bytes]. Copyright