<div dir="ltr"><div><div>I've got another proposed update to PEP 484 ready. There was previously some discussion on python-ideas (Bcc'ed for closure) and quite a bit on the typing issue tracker: <a href="https://github.com/python/typing/issues/107">https://github.com/python/typing/issues/107</a><br><br></div><div>I've worked all that into a patch for PEP 484: <a href="https://github.com/python/typing/pull/218">https://github.com/python/typing/pull/218</a><br><br></div><div>Once we're okay with that I will work on getting the implementation ready in time for Python 3.5.2.<br></div><br></div>Here's the added text:<br><br>Meta-types<br>----------<br><br>A meta-type can be used to indicate a value that is itself a class<br>object that is a subclass of a given class.  It is spelled as<br>``Type[C]`` where ``C`` is a class.  To clarify: while ``C`` (when<br>used as an annotation) refers to instances of class ``C``, ``Type[C]``<br>refers to *subclasses* of ``C``.  (This is a similar distinction as<br>between ``object`` and ``type``.)<br><br>For example, suppose we have the following classes::<br><br>  class User: ...  # Abstract base for User classes<br>  class BasicUser(User): ...<br>  class ProUser(User): ...<br>  class TeamUser(User): ...<br><br>And suppose we have a function that creates an instance of one of<br>these classes if you pass it a class object::<br><br>  def new_user(user_class):<br>      user = user_class()<br>      # (Here we could write the user object to a database)<br>      return user<br><br>Without ``Type[]`` the best we could do to annotate ``new_user()``<br>would be::<br><br>  def new_user(user_class: type) -> User:<br>      ...<br><br>However using ``Type[]`` and a type variable with an upper bound we<br>can do much better::<br><br>  U = TypeVar('U', bound=User)<br>  def new_user(user_class: Type[U]) -> U:<br>      ...<br><br>Now when we call ``new_user()`` with a specific subclass of ``User`` a<br>type checker will infer the correct type of the result::<br><br>  joe = new_user(BasicUser)  # Inferred type is BasicUser<br><br>At runtime the value corresponding to ``Type[C]`` must be an actual<br>class object that's a subtype of ``C``, not a special form.  IOW, in<br>the above example calling e.g. ``new_user(Union[BasicUser, ProUser])``<br>is not allowed.<br><br>There are some concerns with this feature: for example when<br>``new_user()`` calls ``user_class()`` this implies that all subclasses<br>of ``User`` must support this in their constructor signature.  However<br>this is not unique to ``Type[]``: class methods have similar concerns.<br>A type checker ought to flag violations of such assumptions, but by<br>default constructor calls that match the constructor signature in the<br>indicated base class (``User`` in the example above) should be<br>allowed.  A program containing a complex or extensible class hierarchy<br>might also handle this by using a factory class method.<br><br>Plain ``Type`` without brackets is equivalent to using ``type`` (the<br>root of Python's metaclass hierarchy).  This equivalence also<br>motivates the name, ``Type``, as opposed to alternatives like<br>``Class`` or ``SubType``, which were proposed while this feature was<br>under discussion; this is similar to the relationship between<br>e.g. ``List`` and ``list``.<br><br clear="all"><div><div><div><div><br>-- <br><div class="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</div></div></div></div></div>