Add scoping rules for type variables to PEP 484 (#63)

Also clarify the description of NewType() a bit.

Fixes python/typing#249
This commit is contained in:
Ivan Levkivskyi 2016-07-30 01:53:04 +02:00 committed by Guido van Rossum
parent f312480a3b
commit 78478bc886
1 changed files with 91 additions and 5 deletions

View File

@ -448,6 +448,92 @@ is not generic but implicitly inherits from ``Iterable[Any]``::
Generic metaclasses are not supported.
Scoping rules for type variables
--------------------------------
Type variables follow normal name resolution rules.
However, there are some special cases in the static typechecking context:
* A type variable used in a generic function could be inferred to be equal to
different types in the same code block. Example::
from typing import TypeVar, Generic
T = TypeVar('T')
def fun_1(x: T) -> T: ... # T here
def fun_2(x: T) -> T: ... # and here could be different
fun_1(1) # This is OK, T is inferred to be int
fun_2('a') # This is aslo OK, now T is str
* A type variable used in a method of a generic class that coincisides
with one of the variables that parameterize this class is always bound
to that variable. Example::
from typing import TypeVar, Generic
T = TypeVar('T')
class MyClass(Generic[T]):
def meth_1(self, x: T) -> T: ... # T here
def meth_2(self, x: T) -> T: ... # and here are always the same
a = MyClass() # type: MyClass[int]
a.meth_1(1) # OK
a.meth_2('a') # This is an error!
* A type variable used in a method that does not match any of the variables
that parameterize the class makes this method a generic function in that
variable::
T = TypeVar('T')
S = TypeVar('S')
class Foo(Generic[T]):
def method(self, x: T, y: S) -> S:
...
x = Foo() # type: Foo[int]
y = x.method(0, "abc") # inferred type of y is str
* Unbound type variables should not appear in the bodies of generic functions,
or in the class bodies apart from method definitions::
T = TypeVar('T')
S = TypeVar('S')
def a_fun(x: T) -> None:
# this is OK
y = [] # type: List[T]
# but below is an error!
y = [] # type: List[S]
class Bar(Generic[T]):
# this is also an error
an_attr = [] # type: List[S]
def do_something(x: S) -> S: # this is OK though
...
* A generic class definition that appears inside a generic function
should not use type variables that parameterize the generic function::
from typing import List
def a_fun(x: T) -> None:
# This is OK
a_list = [] # type: List[T]
...
# This is however illegal
class MyGeneric(Generic[T]):
...
* A generic class nested in another generic class cannot use the same
type variables, unless the inner class definition is inside a function.
Instantiating generic classes and type erasure
----------------------------------------------
@ -1297,11 +1383,11 @@ from ``UserId`` where ``int`` is expected. Examples::
num = UserId(5) + 1 # type: int
``NewType`` accepts only one argument that shoud be a proper class,
i.e., not a type construct like ``Union``, etc. The function returned
by ``NewType`` accepts only one argument; this is equivalent to supporting
only one constructor accepting an instance of the base class (see above).
Example::
``NewType`` accepts exactly two arguments: a name for the new unique type,
and a base class. The latter should be a proper class, i.e.,
not a type construct like ``Union``, etc. The function returned by ``NewType``
accepts only one argument; this is equivalent to supporting only one
constructor accepting an instance of the base class (see above). Example::
class PacketId:
def __init__(self, major: int, minor: int) -> None: