<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div style="-webkit-text-size-adjust: auto; ">On Jan 16, 2015, at 12:05, "Philipp A." <<a href="mailto:flying-sheep@web.de">flying-sheep@web.de</a>> wrote:</div><div style="-webkit-text-size-adjust: auto; "><br></div><blockquote type="cite" style="-webkit-text-size-adjust: auto; "><div>hi, nice work!<br><br>I like most of the ideas, except the semantic comments and some specific abstract classes.<br><br>so criticism first:<br><br>1. i don’t think comments should ever have an impact on the code.<br>i’d prefer “assert isinstance(...)” for type annotations on variables.<br></div></blockquote><div style="-webkit-text-size-adjust: auto; "><br></div><span style="-webkit-text-size-adjust: auto;">The PEP already acknowledges that the comment solution isn't ideal, but says "</span><span style="-webkit-text-size-adjust: auto; background-color: rgba(255, 255, 255, 0);">If type hinting proves useful in general, a syntax for typing variables may be provided in a future Python version." And it also provides Undefined as an optional alternative way to type variables.</span><div><span style="-webkit-text-size-adjust: auto;"><br></span></div><div><span style="-webkit-text-size-adjust: auto;">But, more importantly, I think you've missed the key point that type annotations are not supposed to affect runtime or compile time at all; they're only there for a separate static type checker. (That could change in the future--at that point, I assume either Guido will come up with a syntax for variable types, or drop explicit variable types.) So this is akin to comments for a linker, docs generator, or test generator.</span></div><div><span style="-webkit-text-size-adjust: auto;"><br></span></div><div><span style="-webkit-text-size-adjust: auto;">Asserts, on the other hand, would be tested at runtime, possibly breaking working code and likely slowing things down.</span><div style="-webkit-text-size-adjust: auto; "><br><blockquote type="cite"><div>2. also i don’t see why Dict, (non-abstract) Set, and List exist as long as we have Mapping and so on. Tuple is different because of its “Multiple return value” status and status as “is treated as Union[Class1, Class2] when used with instanceof(), except and friends”.<br><br>but checking for instanceof(..., list) is unpytonic! imho List and Dict really go against python’s data model and protocol-based nature.<br></div></blockquote><div><br></div><div>This was argued in depth when the idea was first proposed. For the record, I agree that List and friends are more often going to be an attractive nuisance that people will use when they should have used Iterable or Sequence, but if you're going to reopen that argument, you'll want to read the old threads first.</div><div><br></div><div>Also, that's clearly not just a request for clarification, so I think it belongs on the tracker, where the argument can be preserved permanently in a better format than list archives.l</div><br><blockquote type="cite"><div>i’d be for consistency: Set and MutableSet, Sequence and MutableSequence, Mapping and MutableMapping. no “abstract” (because all of this is abstract), no “frozen” (because frozen sets are just immutable sets and immutable behavior is a subset of the corresponding mutable behavior).<br></div></blockquote><div style="-webkit-text-size-adjust: auto; "><br></div>The builtin concrete type frozenset has existed for years. It's an instantiation of the abstract Set type, but (unlike set) not of the MutableSet type. You could argue that they should have been named more consistently, but only if you want to go back to whenever sets.ImmutableSet was renamed frozenset (2.5?) or when the ABCs were first added (2.6/3.0).</div><div style="-webkit-text-size-adjust: auto; "><br><blockquote type="cite"><div>Questions:<br><br>1. will we be able to use Union[...] in places like an except clause, where tuples are used to mean the same right now? would make sense imho<br></div></blockquote><div><br></div><div>Since the elements of a Union are all defined to be subclasses of the Union, it seems like this would automatically work in except clauses, isinstance and issubclass calls, and anywhere else that uses issubclass. But why would you want to?</div><br><blockquote type="cite"><div>2. what are ItemsView and KeysView for? what makes them different from FrozenSet or Sequence?<br></div></blockquote><div style="-webkit-text-size-adjust: auto; "><br></div><div style="-webkit-text-size-adjust: auto; ">They've been in the collections module since 3.0. The documentation already explains why they exist and how they're different from Set. (Actually, I think it's explained more in the docs for the concrete classes associated with dict than in the ABCs, but it's there.)</div><div style="-webkit-text-size-adjust: auto; "><br></div><div style="-webkit-text-size-adjust: auto; ">(You actually asked about FrozenSet and Sequence, not AbstractSet/Set. What makes them different from FrozenSet is that's a generic for the concrete type frozenset; what makes them different from Sequence is that they're not indexable, which is the fundamental thing sequences do.)</div><br><blockquote type="cite"><div><br><div class="gmail_quote">Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>> schrieb am Fri Jan 16 2015 at 18:19:24:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">After a long editing process we've got <a href="https://www.python.org/dev/peps/pep-0484/" target="_blank">PEP 484</a> (Type Hints) ready for your review. This is by no means final, and several areas are either open (to be resolved in a later draft) or postponed (to a different PEP altogether). But there's enough meat that I think we can start having the discussion. Please also see <a href="https://www.python.org/dev/peps/pep-0483/" target="_blank">PEP 483</a> (The Theory of Type Hint; copied and reformatted from the original Quip document that I posted just before last Christmas) and <a href="https://www.python.org/dev/peps/pep-0482/" target="_blank">PEP 482</a> (Literature Overview for Type Hints, by Łukasz). Those are informational PEPs though; the actual spec is focused in PEP 484 (the only one on the Standards Track).<br><br>As I said earlier, I hope to have a rough consensus before <a href="https://us.pycon.org/2015/" target="_blank">PyCon</a> and working code (just the <a href="https://github.com/ambv/typehinting/tree/master/prototyping" target="_blank">typing.py module</a>, really) committed to CPython before <a href="https://www.python.org/dev/peps/pep-0478/" target="_blank">the last 3.5 alpha</a>.<br><br>Here is the raw text of PEP 484. Fire away!!<br><br>PEP: 484<br>Title: Type Hints<br>Version: $Revision$<br>Last-Modified: $Date$<br>Author: Guido van Rossum <<a href="mailto:guido@python.org" target="_blank">guido@python.org</a>>, Jukka Lehtosalo <<a href="mailto:jukka.lehtosalo@iki.fi" target="_blank">jukka.lehtosalo@iki.fi</a>>, Łukasz Langa <<a href="mailto:lukasz@langa.pl" target="_blank">lukasz@langa.pl</a>><br>Discussions-To: Python-Dev <<a href="mailto:python-dev@python.org" target="_blank">python-dev@python.org</a>><br>Status: Draft<br>Type: Standards Track<br>Content-Type: text/x-rst<br>Created: 29-Sep-2014<br>Post-History: 16-Jan-2015<br>Resolution:<br><br><br>Abstract<br>========<br><br>This PEP introduces a standard syntax for type hints using annotations<br>on function definitions.<br><br>The proposal is strongly inspired by mypy [mypy]_.<br><br>The theory behind type hints and gradual typing is explained in PEP 483.<br><br><br>Rationale and Goals<br>===================<br><br>PEP 3107 added support for arbitrary annotations on parts of a function<br>definition.  Although no meaning was assigned to annotations then, there<br>has always been an implicit goal to use them for type hinting, which is<br>listed as the first possible use case in said PEP.<br><br>This PEP aims to provide a standard syntax for type annotations, opening<br>up Python code to easier static analysis and refactoring, potential<br>runtime type checking, and performance optimizations utilizing type<br>information.<br><br><br>Type Definition Syntax<br>======================<br><br>The syntax leverages PEP 3107-style annotations with a number of<br>extensions described in sections below.  In its basic form, type hinting<br>is used by filling function annotations with classes::<br><br>  def greeting(name: str) -> str:<br>      return 'Hello ' + name<br><br>This denotes that the expected type of the ``name`` argument is ``str``.<br>Analogically, the expected return type is ``str``.  Subclasses of<br>a specified argument type are also accepted as valid types for that<br>argument.<br><br>Abstract base classes, types available in the ``types`` module, and<br>user-defined classes may be used as type hints as well.  Annotations<br>must be valid expressions that evaluate without raising exceptions at<br>the time the function is defined.  In addition, the needs of static<br>analysis require that annotations must be simple enough to be<br>interpreted by static analysis tools.  (This is an intentionally<br>somewhat vague requirement.)<br><br>.. FIXME: Define rigorously what is/isn't supported.<br><br>When used as an annotation, the expression ``None`` is considered<br>equivalent to ``NoneType`` (i.e., ``type(None)`` for type hinting<br>purposes.<br><br>Type aliases are also valid type hints::<br><br>  integer = int<br><br>  def retry(url: str, retry_count: integer): ...<br><br>New names that are added to support features described in following<br>sections are available in the ``typing`` package.<br><br><br>Callbacks<br>---------<br><br>Frameworks expecting callback functions of specific signatures might be<br>type hinted using ``Callable[[Arg1Type, Arg2Type], ReturnType]``.<br>Examples::<br><br>  from typing import Any, AnyArgs, Callable<br><br>  def feeder(get_next_item: Callable[[], Item]): ...<br><br>  def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]): ...<br><br>  def partial(func: Callable[AnyArgs, Any], *args): ...<br><br>Since using callbacks with keyword arguments is not perceived as<br>a common use case, there is currently no support for specifying keyword<br>arguments with ``Callable``.<br><br><br>Generics<br>--------<br><br>Since type information about objects kept in containers cannot be<br>statically inferred in a generic way, abstract base classes have been<br>extended to support subscription to denote expected types for container<br>elements.  Example::<br><br>  from typing import Mapping, Set<br><br>  def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]): ...<br><br>Generics can be parametrized by using a new factory available in<br>``typing`` called ``TypeVar``.  Example::<br><br>  from typing import Sequence, TypeVar<br><br>  T = TypeVar('T')      # Declare type variable<br><br>  def first(l: Sequence[T]) -> T:   # Generic function<br>      return l[0]<br><br>In this case the contract is that the returning value is consistent with<br>the elements held by the collection.<br><br>``TypeVar`` supports constraining parametric types to classes with any of<br>the specified bases.  Example::<br><br>  from typing import Iterable<br><br>  X = TypeVar('X')<br>  Y = TypeVar('Y', Iterable[X])<br><br>  def filter(rule: Callable[[X], bool], input: Y) -> Y:<br>      ...<br><br>.. FIXME: Add an example with multiple bases defined.<br><br>In the example above we specify that ``Y`` can be any subclass of<br>Iterable with elements of type ``X``, as long as the return type of<br>``filter()`` will be the same as the type of the ``input``<br>argument.<br><br>.. FIXME: Explain more about how this works.<br><br><br>Forward references<br>------------------<br><br>When a type hint contains names that have not been defined yet, that<br>definition may be expressed as a string, to be resolved later.  For<br>example, instead of writing::<br><br>  def notify_by_email(employees: Set[Employee]): ...<br><br>one might write::<br><br>  def notify_by_email(employees: 'Set[Employee]'): ...<br><br>.. FIXME: Rigorously define this.  Defend it, or find an alternative.<br><br><br>Union types<br>-----------<br><br>Since accepting a small, limited set of expected types for a single<br>argument is common, there is a new special factory called ``Union``.<br>Example::<br><br>  from typing import Union<br><br>  def handle_employees(e: Union[Employee, Sequence[Employee]]):<br>      if isinstance(e, Employee):<br>          e = [e]<br>      ...<br><br>A type factored by ``Union[T1, T2, ...]`` responds ``True`` to<br>``issubclass`` checks for ``T1`` and any of its subclasses, ``T2`` and<br>any of its subclasses, and so on.<br><br>One common case of union types are *optional* types.  By default,<br>``None`` is an invalid value for any type, unless a default value of<br>``None`` has been provided in the function definition.  Examples::<br><br>  def handle_employee(e: Union[Employee, None]): ...<br><br>As a shorthand for ``Union[T1, None]`` you can write ``Optional[T1]``;<br>for example, the above is equivalent to::<br><br>  from typing import Optional<br><br>  def handle_employee(e: Optional[Employee]): ...<br><br>An optional type is also automatically assumed when the default value is<br>``None``, for example::<br><br>  def handle_employee(e: Employee = None): ...<br><br>This is equivalent to::<br><br>  def handle_employee(e: Optional[Employee] = None): ...<br><br>.. FIXME: Is this really a good idea?<br><br>A special kind of union type is ``Any``, a class that responds<br>``True`` to ``issubclass`` of any class.  This lets the user<br>explicitly state that there are no constraints on the type of a<br>specific argument or return value.<br><br><br>Platform-specific type checking<br>-------------------------------<br><br>In some cases the typing information will depend on the platform that<br>the program is being executed on.  To enable specifying those<br>differences, simple conditionals can be used::<br><br>  from typing import PY2, WINDOWS<br><br>  if PY2:<br>      text = unicode<br>  else:<br>      text = str<br><br>  def f() -> text: ...<br><br>  if WINDOWS:<br>      loop = ProactorEventLoop<br>  else:<br>      loop = UnixSelectorEventLoop<br><br>Arbitrary literals defined in the form of ``NAME = True`` will also be<br>accepted by the type checker to differentiate type resolution::<br><br>  DEBUG = False<br>  ...<br>  if DEBUG:<br>      class Tracer:<br>          <verbose implementation><br>  else:<br>      class Tracer:<br>          <dummy implementation><br><br>For the purposes of type hinting, the type checker assumes ``__debug__``<br>is set to ``True``, in other words the ``-O`` command-line option is not<br>used while type checking.<br><br><br>Compatibility with other uses of function annotations<br>-----------------------------------------------------<br><br>A number of existing or potential use cases for function annotations<br>exist, which are incompatible with type hinting.  These may confuse a<br>static type checker.  However, since type hinting annotations have no<br>run time behavior (other than evaluation of the annotation expression<br>and storing annotations in the ``__annotations__`` attribute of the<br>function object), this does not make the program incorrect -- it just<br>makes it issue warnings when a static analyzer is used.<br><br>To mark portions of the program that should not be covered by type<br>hinting, use the following:<br><br>* a ``@no_type_checks`` decorator on classes and functions<br><br>* a ``# type: ignore`` comment on arbitrary lines<br><br>.. FIXME: should we have a module-wide comment as well?<br><br><br>Type Hints on Local and Global Variables<br>========================================<br><br>No first-class syntax support for explicitly marking variables as being<br>of a specific type is added by this PEP.  To help with type inference in<br>complex cases, a comment of the following format may be used::<br><br>  x = []   # type: List[Employee]<br><br>In the case where type information for a local variable is needed before<br>if was declared, an ``Undefined`` placeholder might be used::<br><br>  from typing import Undefined<br><br>  x = Undefined   # type: List[Employee]<br>  y = Undefined(int)<br><br>If type hinting proves useful in general, a syntax for typing variables<br>may be provided in a future Python version.<br><br><br>Explicit raised exceptions<br>==========================<br><br>No support for listing explicitly raised exceptions is being defined by<br>this PEP.  Currently the only known use case for this feature is<br>documentational, in which case the recommendation is to put this<br>information in a docstring.<br><br><br>The ``typing`` package<br>======================<br><br>To open the usage of static type checking to Python 3.5 as well as older<br>versions, a uniform namespace is required.  For this purpose, a new<br>package in the standard library is introduced called ``typing``.  It<br>holds a set of classes representing builtin types with generics, namely:<br><br>* Dict, used as ``Dict[key_type, value_type]``<br><br>* List, used as ``List[element_type]``<br><br>* Set, used as ``Set[element_type]``. See remark for ``AbstractSet``<br>  below.<br><br>* FrozenSet, used as ``FrozenSet[element_type]``<br><br>* Tuple, used as ``Tuple[index0_type, index1_type, ...]``.<br>  Arbitrary-length tuples might be expressed using ellipsis, in which<br>  case the following arguments are considered the same type as the last<br>  defined type on the tuple.<br><br>It also introduces factories and helper members needed to express<br>generics and union types:<br><br>* Any, used as ``def get(key: str) -> Any: ...``<br><br>* Union, used as ``Union[Type1, Type2, Type3]``<br><br>* TypeVar, used as ``X = TypeVar('X', Type1, Type2, Type3)`` or simply<br>  ``Y = TypeVar('Y')``<br><br>* Undefined, used as ``local_variable = Undefined # type: List[int]`` or<br>  ``local_variable = Undefined(List[int])`` (the latter being slower<br>  during runtime)<br><br>* Callable, used as ``Callable[[Arg1Type, Arg2Type], ReturnType]``<br><br>* AnyArgs, used as ``Callable[AnyArgs, ReturnType]``<br><br>* AnyStr, equivalent to ``TypeVar('AnyStr', str, bytes)``<br><br>All abstract base classes available in ``collections.abc`` are<br>importable from the ``typing`` package, with added generics support:<br><br>* ByteString<br><br>* Callable<br><br>* Container<br><br>* Hashable<br><br>* ItemsView<br><br>* Iterable<br><br>* Iterator<br><br>* KeysView<br><br>* Mapping<br><br>* MappingView<br><br>* MutableMapping<br><br>* MutableSequence<br><br>* MutableSet<br><br>* Sequence<br><br>* Set as ``AbstractSet``. This name change was required because ``Set``<br>  in the ``typing`` module means ``set()`` with generics.<br><br>* Sized<br><br>* ValuesView<br><br>* Mapping<br><br>The library includes literals for platform-specific type hinting:<br><br>* PY2<br><br>* PY3, equivalent to ``not PY2``<br><br>* WINDOWS<br><br>* UNIXOID, equivalent to ``not WINDOWS``<br><br>The following types are available in the ``<a href="http://typing.io" target="_blank">typing.io</a>`` module:<br><br>* IO<br><br>* BinaryIO<br><br>* TextIO<br><br>The following types are provided by the ``<a href="http://typing.re" target="_blank">typing.re</a>`` module:<br><br>* Match and Pattern, types of ``re.match()`` and ``re.compile()``<br>  results<br><br>As a convenience measure, types from ``<a href="http://typing.io" target="_blank">typing.io</a>`` and ``<a href="http://typing.re" target="_blank">typing.re</a>`` are<br>also available in ``typing`` (quoting Guido, "There's a reason those<br>modules have two-letter names.").<br><br><br>The place of the ``typing`` module in the standard library<br>----------------------------------------------------------<br><br>.. FIXME: complete this section<br><br><br>Usage Patterns<br>==============<br><br>The main use case of type hinting is static analysis using an external<br>tool without executing the analyzed program.  Existing tools used for<br>that purpose like ``pyflakes`` [pyflakes]_ or ``pylint`` [pylint]_<br>might be extended to support type checking.  New tools, like mypy's<br>``mypy -S`` mode, can be adopted specifically for this purpose.<br><br>Type checking based on type hints is understood as a best-effort<br>mechanism.  In other words, whenever types are not annotated and cannot<br>be inferred, the type checker considers such code valid.  Type errors<br>are only reported in case of explicit or inferred conflict.  Moreover,<br>as a mechanism that is not tied to execution of the code, it does not<br>affect runtime behaviour.  In other words, even in the case of a typing<br>error, the program will continue running.<br><br>The implementation of a type checker, whether linting source files or<br>enforcing type information during runtime, is out of scope for this PEP.<br><br>.. FIXME: Describe stub modules.<br><br>.. FIXME: Describe run-time behavior of generic types.<br><br><br>Existing Approaches<br>===================<br><br>PEP 482 lists existing approaches in Python and other languages.<br><br><br>Is type hinting Pythonic?<br>=========================<br><br>Type annotations provide important documentation for how a unit of code<br>should be used.  Programmers should therefore provide type hints on<br>public APIs, namely argument and return types on functions and methods<br>considered public.  However, because types of local and global variables<br>can be often inferred, they are rarely necessary.<br><br>The kind of information that type hints hold has always been possible to<br>achieve by means of docstrings.  In fact, a number of formalized<br>mini-languages for describing accepted arguments have evolved.  Moving<br>this information to the function declaration makes it more visible and<br>easier to access both at runtime and by static analysis.  Adding to that<br>the notion that “explicit is better than implicit”, type hints are<br>indeed *Pythonic*.<br><br><br>Acknowledgements<br>================<br><br>This document could not be completed without valuable input,<br>encouragement and advice from Jim Baker, Jeremy Siek, Michael Matson<br>Vitousek, Andrey Vlasovskikh, and Radomir Dopieralski.<br><br>Influences include existing languages, libraries and frameworks<br>mentioned in PEP 482.  Many thanks to their creators, in alphabetical<br>order: Stefan Behnel, William Edwards, Greg Ewing, Larry Hastings,<br>Anders Hejlsberg, Alok Menghrajani, Travis E. Oliphant, Joe Pamer,<br>Raoul-Gabriel Urma, and Julien Verlaguet.<br><br><br>References<br>==========<br><br>.. [mypy]<br>   <a href="http://mypy-lang.org" target="_blank">http://mypy-lang.org</a><br><br>.. [pyflakes]<br>   <a href="https://github.com/pyflakes/pyflakes/" target="_blank">https://github.com/pyflakes/pyflakes/</a><br><br>.. [pylint]<br>   <a href="http://www.pylint.org" target="_blank">http://www.pylint.org</a><br><br><br>Copyright<br>=========<br><br>This document has been placed in the public domain.<br><br><br> <br>..<br>   Local Variables:<br>   mode: indented-text<br>   indent-tabs-mode: nil<br>   sentence-end-double-space: t<br>   fill-column: 70<br>   coding: utf-8<br>   End:<br><br clear="all"><div><br>-- <br><div>--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</div></div>
______________________________<u></u>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" target="_blank">https://mail.python.org/<u></u>mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" target="_blank">http://python.org/psf/<u></u>codeofconduct/</a></blockquote></div>
</div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>Python-ideas mailing list</span><br><span><a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a></span><br><span><a href="https://mail.python.org/mailman/listinfo/python-ideas">https://mail.python.org/mailman/listinfo/python-ideas</a></span><br><span>Code of Conduct: <a href="http://python.org/psf/codeofconduct/">http://python.org/psf/codeofconduct/</a></span></div></blockquote></div></div></body></html>