Small edits; added Tuple[t, ...] and Callable[..., tr].
This commit is contained in:
parent
f80066c3fb
commit
d7aefb884c
61
pep-0483.txt
61
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 <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
|
||||
|
|
Loading…
Reference in New Issue