Small edits; added Tuple[t, ...] and Callable[..., tr].

This commit is contained in:
Guido van Rossum 2015-04-06 19:54:09 -07:00
parent f80066c3fb
commit d7aefb884c
1 changed files with 31 additions and 30 deletions

View File

@ -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 <http://mypy.readthedocs.org/en/latest/generics.html>`_.)
- **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 <http://mypy.readthedocs.org/en/latest/generics.html>`_.)
- 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 <http://mypy.readthedocs.org/en/latest/generics.html>`_.)
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 <https://github.com/JukkaL/typing/blob/master/typing.py>`_.)
(See also the `typing.py module
<https://github.com/ambv/typehinting/blob/master/prototyping/typing.py>`_.)
- 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