ASCIIfy PEP 483

This commit is contained in:
Chris Angelico 2015-01-10 05:28:21 +11:00
parent 9ba23eff34
commit 24dc240fc2
1 changed files with 28 additions and 28 deletions

View File

@ -40,8 +40,8 @@ Summary of gradual typing
We define a new relationship, is-consistent-with, which is similar to We define a new relationship, is-consistent-with, which is similar to
is-subclass-of, except it is not transitive when the new type **Any** is is-subclass-of, except it is not transitive when the new type **Any** is
involved. (Neither relationship is symmetric.) Assigning x to y is OK if involved. (Neither relationship is symmetric.) Assigning x to y is OK if
the type of x is consistent with the type of y. (Compare this to “... if the type of x is consistent with the type of y. (Compare this to "... if
the type of x is a subclass of the type of y, which states one of the the type of x is a subclass of the type of y," which states one of the
fundamentals of OO programming.) The is-consistent-with relationship is fundamentals of OO programming.) The is-consistent-with relationship is
defined by three rules: defined by three rules:
@ -58,12 +58,12 @@ for a longer explanation and motivation. Note that rule 3 places **Any**
at the root of the class graph. This makes it very similar to at the root of the class graph. This makes it very similar to
**object**. The difference is that **object** is not consistent with **object**. The difference is that **object** is not consistent with
most types (e.g. you can't use an object() instance where an int is most types (e.g. you can't use an object() instance where an int is
expected). IOW both **Any** and **object** mean “any type is allowed” expected). IOW both **Any** and **object** mean "any type is allowed"
when used to annotate an argument, but only **Any** can be passed no when used to annotate an argument, but only **Any** can be passed no
matter what type is expected (in essence, **Any** shuts up complaints matter what type is expected (in essence, **Any** shuts up complaints
from the static checker). from the static checker).
Here's an example showing how these rules work out in practice: Here's an example showing how these rules work out in practice:
Say we have an Employee class, and a subclass Manager: Say we have an Employee class, and a subclass Manager:
@ -72,7 +72,7 @@ Say we have an Employee class, and a subclass Manager:
Let's say variable e is declared with type Employee: Let's say variable e is declared with type Employee:
- e = Employee()  # type: Employee - e = Employee() # type: Employee
Now it's okay to assign a Manager instance to e (rule 1): Now it's okay to assign a Manager instance to e (rule 1):
@ -81,40 +81,40 @@ Now it's okay to assign a Manager instance to e (rule 1):
It's not okay to assign an Employee instance to a variable declared with It's not okay to assign an Employee instance to a variable declared with
type Manager: type Manager:
- m = Manager()  # 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**: However, suppose we have a variable whose type is **Any**:
- a = some\_func()  # type: Any - a = some\_func() # type: Any
Now it's okay to assign a to e (rule 2): Now it's okay to assign a to e (rule 2):
- e = a  # OK - e = a # OK
Of course it's also okay to assign e to a (rule 3), but we didn't need Of course it's also okay to assign e to a (rule 3), but we didn't need
the concept of consistency for that: the concept of consistency for that:
- a = e  # OK - a = e # OK
Notational conventions Notational conventions
---------------------- ----------------------
- t1, t2 etc.  and u1, u2 etc. are types or classes. Sometimes we write - 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.” 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 Var(), see below).
- C, D etc. are classes defined with a class statement. - C, D etc. are classes defined with a class statement.
- x, y etc. are objects or instances. - x, y etc. are objects or instances.
- We use the terms type and class interchangeably, and we assume - We use the terms type and class interchangeably, and we assume
type(x) is x.\_\_class\_\_. type(x) is x.\_\_class\_\_.
General rules General rules
------------- -------------
- Instance-ness is  derived from class-ness, e.g. x is an instance of - Instance-ness is derived from class-ness, e.g. x is an instance of
t1 if  type(x) is a subclass of t1. t1 if type(x) is a subclass of t1.
- No types defined below (i.e. Any, Union etc.) can be instantiated. - No types defined below (i.e. Any, Union etc.) can be instantiated.
(But non-abstract subclasses of Generic can be.) (But non-abstract subclasses of Generic can be.)
- No types defined below can be subclassed, except for Generic and - No types defined below can be subclassed, except for Generic and
@ -136,7 +136,7 @@ Types
Union the result is flattened. (Example: Union[int, Union[float, Union the result is flattened. (Example: Union[int, Union[float,
str]] == Union[int, float, str].) If ti and tj have a subclass str]] == Union[int, float, str].) If ti and tj have a subclass
relationship, the less specific type survives. (Example: relationship, the less specific type survives. (Example:
Union[Employee, Manager] == Union[Employee].) Union[t1] returns just Union[Employee, Manager] == Union[Employee].) Union[t1] returns just
t1. Union[] is illegal, so is Union[()]. Corollary: Union[..., Any, t1. Union[] is illegal, so is Union[()]. Corollary: Union[..., Any,
...] returns Any; Union[..., object, ...] returns object; to cut a ...] returns Any; Union[..., object, ...] returns object; to cut a
tie, Union[Any, object] == Union[object, Any] == Any. tie, Union[Any, object] == Union[object, Any] == Any.
@ -154,13 +154,13 @@ Types
argument types t1 etc., and return type tr. The argument list may be 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 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 arguments, nor varargs (we don't need to spell those often enough to
complicate the syntax however, Reticulated Python has a useful idea complicate the syntax - however, Reticulated Python has a useful idea
here). This is covariant in the return type, but contravariant in the here). This is covariant in the return type, but contravariant in the
arguments. “Covariant” here means that for two callable types that arguments. "Covariant" here means that for two callable types that
differ only in the return type, the subclass relationship for the differ only in the return type, the subclass relationship for the
callable types follows that of the return types. (Example: callable types follows that of the return types. (Example:
Callable[[], Manager] is a subclass of Callable[[], Employee].) Callable[[], Manager] is a subclass of Callable[[], Employee].)
“Contravariant” here means that for two callable types that differ "Contravariant" here means that for two callable types that differ
only in the type of one argument, the subclass relationship for the only in the type of one argument, the subclass relationship for the
callable types goes in the opposite direction as for the argument callable types goes in the opposite direction as for the argument
types. (Example: Callable[[Employee], None] is a subclass of types. (Example: Callable[[Employee], None] is a subclass of
@ -198,13 +198,13 @@ are still controversial or not fully specified.)
- Type aliases, e.g. - Type aliases, e.g.
* point = Tuple[float, float] * point = Tuple[float, float]
* def distance(p: point) -> float: ...  * def distance(p: point) -> float: ...
- Forward references via strings, e.g. - Forward references via strings, e.g.
* class C: * 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.
@ -213,11 +213,11 @@ are still controversial or not fully specified.)
- Don't use dynamic type expressions; use builtins and imported types - Don't use dynamic type expressions; use builtins and imported types
only. No 'if'. 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. - Type declaration in comments, e.g.
* x = []  # type: Sequence[int] * x = [] # type: Sequence[int]
- Type declarations using Undefined, e.g. - Type declarations using Undefined, e.g.
@ -237,7 +237,7 @@ generics <http://mypy.readthedocs.org/en/latest/generics.html>`_.)
the variable name. the variable name.
- **Y = Var('Y', t1, t2, ...).** Ditto, constrained to t1 etc. Behaves - **Y = Var('Y', t1, t2, ...).** Ditto, constrained to t1 etc. Behaves
 like Union[t1, t2, ...] for most purposes, but when used as a type 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 variable, subclasses of t1 etc. are replaced by the most-derived base
class among t1 etc. class among t1 etc.
@ -249,9 +249,9 @@ generics <http://mypy.readthedocs.org/en/latest/generics.html>`_.)
- return a if len(a) >= len(b) else b - 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 * 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 (str or bytes), and moreover, even if the arguments are instances of a
@ -290,7 +290,7 @@ generics <http://mypy.readthedocs.org/en/latest/generics.html>`_.)
- **class C(Generic[X, Y, ...]):** ... Define a generic class C over type - **class C(Generic[X, Y, ...]):** ... Define a generic class C over type
variables X etc. C itself becomes parameterizable, e.g. C[int, str, ...] variables X etc. C itself becomes parameterizable, e.g. C[int, str, ...]
is a specific class with substitutions Xint etc. is a specific class with substitutions X->int etc.
- TODO: Explain use of generic types in function signatures. E.g. - TODO: Explain use of generic types in function signatures. E.g.
Sequence[X], Sequence[int], Sequence[Tuple[X, Y, Z]], and mixtures. Sequence[X], Sequence[int], Sequence[Tuple[X, Y, Z]], and mixtures.
@ -316,7 +316,7 @@ module <https://github.com/JukkaL/typing/blob/master/typing.py>`_.)
Another reference Another reference
----------------- -----------------
Lest mypy gets all the attention, I should mention \ `Reticulated Lest mypy gets all the attention, I should mention \ `Reticulated
Python <https://github.com/mvitousek/reticulated>`_ by Michael Vitousek Python <https://github.com/mvitousek/reticulated>`_ by Michael Vitousek
as an example of a slightly different approach to gradual typing for as an example of a slightly different approach to gradual typing for
Python. It is described in an actual `academic Python. It is described in an actual `academic