Skip to content

Commit 19a32e0

Browse files
author
Guido van Rossum
committed
Add text about Type[C].
This addresses #107 (but it doen't close it because the issue also calls for an implementation in typing.py).
1 parent f0ed85c commit 19a32e0

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

pep-0484.txt

+66
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,72 @@ allow all operations on it, and a value of type ``Any`` can be assigned
861861
to a variable (or used as a return value) of a more constrained type.
862862

863863

864+
Meta-types
865+
----------
866+
867+
A meta-type can be used to indicate a value that is itself a class
868+
object that is a subclass of a given class. It is spelled as
869+
``Type[C]`` where ``C`` is a class. To clarify: while ``C`` (when
870+
used as an annotation) refers to instances of class ``C``, ``Type[C]``
871+
refers to *subclasses* of ``C``. (This is a similar distinction as
872+
between ``object`` and ``type``.)
873+
874+
For example, suppose we have the following classes::
875+
876+
class User: ... # Abstract base for User classes
877+
class BasicUser(User): ...
878+
class ProUser(User): ...
879+
class TeamUser(User): ...
880+
881+
And suppose we have a function that creates an instance of one of
882+
these classes if you pass it a class object::
883+
884+
def new_user(user_class):
885+
user = user_class()
886+
# (Here we could write the user object to a database)
887+
return user
888+
889+
Without ``Type[]`` the best we could do to annotate ``new_user()``
890+
would be::
891+
892+
def new_user(user_class: type) -> User:
893+
...
894+
895+
However using ``Type[]`` and a type variable with an upper bound we
896+
can do much better::
897+
898+
U = TypeVar('U', bound=User)
899+
def new_user(user_class: Type[U]) -> U:
900+
...
901+
902+
Now when we call ``new_user()`` with a specific subclass of ``User`` a
903+
type checker will infer the correct type of the result::
904+
905+
joe = new_user(BasicUser) # Inferred type is BasicUser
906+
907+
At runtime the value corresponding to ``Type[C]`` must be an actual
908+
class object that's a subtype of ``C``, not a special form. IOW, in
909+
the above example calling e.g. ``new_user(Union[BasicUser, ProUser])``
910+
is not allowed.
911+
912+
There are some concerns with this feature: for example when
913+
``new_user()`` calls ``user_class()`` this implies that all subclasses
914+
of ``User`` must support this in their constructor signature. However
915+
this is not unique to ``Type[]``: class methods have similar concerns.
916+
A type checker ought to flag violations of such assumptions, but by
917+
default constructor calls that match the constructor signature in the
918+
indicated base class (``User`` in the example above) should be
919+
allowed. A program containing a complex or extensible class hierarchy
920+
might also handle this by using a factory class method.
921+
922+
Plain ``Type`` without brackets is equivalent to using ``type`` (the
923+
root of Python's metaclass hierarchy). This equivalence also
924+
motivates the name, ``Type``, as opposed to alternatives like
925+
``Class`` or ``SubType``, which were proposed while this feature was
926+
under discussion; this is similar to the relationship between
927+
e.g. ``List`` and ``list``.
928+
929+
864930
Version and platform checking
865931
-----------------------------
866932

0 commit comments

Comments
 (0)