Skip to content

Conversation

@Michael0x2a
Copy link
Collaborator

This pull request expands our "getting started" docs so they discuss how to use type hints in more detail.

In general, I'm hoping this pull request will accomplish two main things:

  1. Give users a better "tour" of the available PEP 484 types.

  2. Do a better job of giving users a "heads-up" of common gotchas: for example, how dynamically typed functions aren't type-checked.

Here's a list of specific changes I made:

  1. I combined "Installing mypy" and "Running mypy" into one section.

  2. I modified the "Function signatures" section to focus more on the distinction between dynamic and static typing: I suspect that's a common tripup new users run into.

    I also changed the examples so they'll actually produce a runtime error if you misuse them.

  3. I moved the existing text on annotating no-argument functions or functions with default arguments into a separate "More function signatures" to try and keep the new "Function signatures and dynamic vs static typing" section focused.

  4. I expanded the section about using the "typing" module to be more thorough. In particular, I wanted to expose the user to the concept of concrete generic types (List), abstract generic types/protocols (Iterable), and to more non-conventional types like Union.

    I think these three examples are broadly representative of the different "flavors" of PEP 484 types and so should help new users be a little more aware of the kinds of things they can do with types.

    The main thing that's missing is an introduction to custom generic classes and functions: that's probably too complex of a topic to belong in this page.

  5. I added a section on local type inference: it's a new concept for people who are more used to languages like Java or C# so felt like it was worth mentioning.

    This section also covers the other stumbling block I think new users are likely to run into: the "Need type annotation for 'variable'" error message.

  6. I added a section on customizing mypy via the command line flags. I don't think enough users are aware that you can do this, despite how useful the flags can be.

This pull request expands our "getting started" docs so they discuss how
to use type hints in more detail.

In general, I'm hoping this pull request will accomplish two main
things:

1. Give users a better "tour" of the available PEP 484 types.

2. Do a better job of giving users a "heads-up" of common gotchas:
   for example, how dynamically typed functions aren't type-checked.

Here's a list of specific changes I made:

1. I combined "Installing mypy" and "Running mypy" into one section.

2. I modified the "Function signatures" section to focus more on the
   distinction between dynamic and static typing: I suspect that's
   a common tripup new users run into.

   I also changed the examples so they'll actually produce a runtime
   error if you misuse them.

3. I moved the existing text on annotating no-argument functions or
   functions with default arguments into a separate "More function
   signatures" to try and keep the new "Function signatures and and
   dynamic vs static typing" section focused.

4. I expanded the section about using the "typing" module to be more
   thorough. In particular, I wanted to expose the user to the concept
   of concrete generic types (List), abstract generic types/protocols
   (Iterable), and to more non-conventional types like Union.

   I think these three examples are broadly representative of the
   different "flavors" of PEP 484 types and so should help new users
   be a little more aware of the kinds of things they can do with types.

   The main thing that's missing is an introduction to custom generic
   classes and functions: that's probably too complex of a topic to
   belong in this page.

5. I added a section on local type inference: it's a new concept for
   people who are more used to languages like Java or C# so felt like
   it was worth mentioning.

   This section also covers the final stumbling block I think new users
   are likely to run into: the "Need type annotation for 'variable'"
   error message.

6. I added a section on customizing mypy via the command line flags.
   I don't think enough users are aware that you can do this, despite
   how useful the flags can be.
generic types) by looking through the
:ref:`type system reference <overview-type-system-reference>`.

One final note: when adding types, the convention is to import types
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it also fair to say that it is conventional to put typing imports as the first imports? (It seems like it to me, at least).

If it's not actually a common convention, then it shouldn't derail this PR, but if it is I think it will be nice to mention.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I also personally like that style (and I think mypy itself also follows that convention), but I'm thinking it's probably best to not mention this for now -- I'm not sure if other Python linters have caught up on this convention yet. For example, I think isort will sort imports alphabetically?

Copy link
Member

Choose a reason for hiding this comment

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

I don't have a strong preference, but I also like typing imports first. isort however has a different opinion (maybe it is configurable, I have very little experience with it).

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think that this convention is followed very widely. The mypy implementation doesn't consistently put typing imports first. I would rather not recommend any particular placement for the imports.

Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

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

Thanks for improving our docs! This should make it easier for new users to get started. Left a bunch of mostly minor comments.

def f():
1 + 'x' # No static type error (dynamically typed)
def stars(*names: str, **kwargs: float) -> float:
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think that this example is a bit too clever. Maybe instead write too simpler (unrelated) functions, one for demonstrating *args and the other for **kwargs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I decided to just give up on trying to come up with a motivated example in this case and just left in comments describing what types 'args' and 'kwargs' would have.

generic types) by looking through the
:ref:`type system reference <overview-type-system-reference>`.

One final note: when adding types, the convention is to import types
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think that this convention is followed very widely. The mypy implementation doesn't consistently put typing imports first. I would rather not recommend any particular placement for the imports.

add a dynamically-typed function by mistake. You can make mypy do this
by running mypy with the ``--disallow-untyped-defs`` flag.

One particularly useful command is the ``--strict`` flag. Running
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure if we should recommend --strict here. Even mypy doesn't use all the options it enables yet. At least I think that there is too much emphasis on it now. I think it might be okay to mention it here as option for people who want to go the extra mile.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ok, I decreased the emphasis a bit -- let me know if you want me to go even further.

@JukkaL
Copy link
Collaborator

JukkaL commented Jan 21, 2019

Two more things:

  • Optional[x] is very common -- more common than regular union types. Maybe at least add a quick mention?
  • Maybe also quickly introduce Tuple[...], since tuple types are common.

- Fix small suggestions made
- Simplify the `*args` and `**kwargs` example (or rather, just give up
  on constructing an example altogether)
- Sneak in an example of `Tuple[...]` when discussing `*args`
- Discuss `Optional[...]` -- and also sneak in an example of mypy
  understanding `x is None` checks.
@Michael0x2a
Copy link
Collaborator Author

@ilevkivskyi and @JukkaL -- ok, this should be ready for a second look whenever!

@JukkaL -- I added in a section about Optional types, as suggested. I also tried adding in some discussion of Tuple, but everything I tried adding felt a little bloated. I think as a compromise, what I'll do is submit a follow-up diff where I expand the "built-in types" page and have the "getting started" page directly link to that.

.. code-block:: python
# If you are using Python 3.6+, you can use variable annotations.
# See https://www.python.org/dev/peps/pep-0526/ for more on variable annotations.
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 a clickable link would look better. For example, ...we could `annotate <pep526_>`_ it... in the text above. Or maybe just abandon this idea, in any case non-clickable links look bad in the docs.

Also I thought most of the documentation uses "you could..." style, but you have couple of "we" in that sentence above.

Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

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

Thanks for the updates! Looks good to me now, just one minor comment.

print('Hello, {}'.format(name))
print('Hello ' + name)
As a final example, suppose want to write a function that can accept *either*
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: this is no longer the final example.

@Michael0x2a Michael0x2a merged commit 9ffb7ca into python:master Feb 1, 2019
@Michael0x2a Michael0x2a deleted the expand-getting-started branch February 1, 2019 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants