8000 Add text about Type[C]. by gvanrossum · Pull Request #218 · python/typing · GitHub
[go: up one dir, main page]

Skip to content

Add text about Type[C]. #218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 18, 2016
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
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).
  • Loading branch information
Guido van Rossum committed May 13, 2016
commit 19a32e04b5864f8ff602038fd8ddb3d2ef70b96b
66 changes: 66 additions & 0 deletions pep-0484.txt
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,72 @@ allow all operations on it, and a value of type ``Any`` can be assigned
to a variable (or used as a return value) of a more constrained type.


Meta-types
----------
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "Meta-types" is not a good name for this section for four reasons:

  1. This could add to the classes vs. types confusion: Unlike metaclasses that are quite different from classes, types do not have such hierarchy, since one should not type annotate types, one can only type annotate classes.
  2. Type[C] has normal semantics of type: This is just a set of objects that respond True to issubclass(objc, C).
  3. I think someone who is looking for a documentation of this feature will not look for "Meta-types", therefore I would propose to change this to a simpler title, like "Type annotating class objects".
  4. Finally, using such terminology could lead to proliferation of "meta": If we call annotations of values that are class objects by Type[C] or by ABCMeta meta-types, then how are we supposed to call annotations of values that are metaclasses (by Type[ABCMeta] for example)? Meta-meta-types? :-)


A meta-type can be used to indicate a value that is itself a class
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the comment above, I would replace this by "An additional fundamental building block can be used to indicate a value that..." Putting Type in a row with other building blocks like Tuple etc.,will emphasize, that although C must be a class, Type[C] is a normal type that can be used elsewhere:

registry = [] # type: List[Tuple[int, Type[FrameworkBase]]]

object that is a subclass of a given class. It is spelled as
``Type[C]`` where ``C`` is a class. To clarify: while ``C`` (when
used as an annotation) refers to instances of class ``C``, ``Type[C]``
refers to *subclasses* of ``C``. (This is a similar distinction as
between ``object`` and ``type``.)

For example, suppose we have the following classes::

class User: ... # Abstract base for User classes
class BasicUser(User): ...
class ProUser(User): ...
class TeamUser(User): ...

And suppose we have a function that creates an instance of one of
these classes if you pass it a class object::

def new_user(user_class):
user = user_class()
# (Here we could write the user object to a database)
return user

Without ``Type[]`` the best we could do to annotate ``new_user()``
would be::

def new_user(user_class: type) -> User:
...

However using ``Type[]`` and a type variable with an upper bound we
can do much better::

U = TypeVar('U', bound=User)
def new_user(user_class: Type[U]) -> U:
...

Now when we call ``new_user()`` with a specific subclass of ``User`` a
type checker will infer the correct type of the result::

joe = new_user(BasicUser) # Inferred type is BasicUser

At runtime the value corresponding to ``Type[C]`` must be an actual
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove "At runtime". Just "The value corresponding to..."

class object that's a subtype of ``C``, not a special form. IOW, in
the above example calling e.g. ``new_user(Union[BasicUser, ProUser])``
is not allowed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe replace here "is not allowed" by "is rejected by the type checker"? Calling new_user(Union[BasicUser, ProUser]) will trigger TypeError because it tries to instantiate Union, but I think it is not what you wanted to say.


There are some concerns with this feature: for example when
``new_user()`` calls ``user_class()`` this implies that all subclasses
of ``User`` must support this in their constructor signature. However
this is not unique to ``Type[]``: class methods have similar concerns.
A type checker ought to flag violations of such assumptions, but by
default constructor calls that match the constructor signature in the
indicated base class (``User`` in the example above) should be
allowed. A program containing a complex or extensible class hierarchy
might also handle this by using a factory class method.

Plain ``Type`` without brackets is equivalent to using ``type`` (the
root of Python's metaclass hierarchy). This equivalence also
motivates the name, ``Type``, as opposed to alternatives like
``Class`` or ``SubType``, which were proposed while this feature was
under discussion; this is similar to the relationship between
e.g. ``List`` and ``list``.


Version and platform checking
-----------------------------

Expand Down
0