Type Hinting in PyCharm
Enabling postponed evaluation of annotations
PyCharm supports changes introduced in PEP-563. With these changes, function and variable annotations are no longer evaluated at function definition time. Instead, a new __future__
import enables their postponed evaluation. Consider the following sample code:
class Foo:
def foo(self) -> 'Foo': ...
class Bar:
def bar(self, param: 'Bar'): ...
__future__
import applied, you can benefit from forward references and avoid using string literals for class definitions: from __future__ import annotations
class Foo:
def foo(self) -> Foo: ...
class Bar:
def bar(self, param: Bar): ...
Support for PEP 484 type hints
PyCharm supports type hinting in function annotations and type comments using the typing
module defined by PEP 484.
NewType Support
TheNewType
helper function in PEP 484 facilitates creating simple classes. Its support can be enabled in PyCharm by adding the corresponding import. Below is the example that solves a task opposite to one exampled in PEP 484. It builds a user Id by a user name. from typing import NewType
UserName = NewType('UserName', str)
def id_by_name (user_name: UserName) -> int:
pass
UserName(33) # Integer is not allowed - correct warning
id_by_name('John') # String is also not allowed - correct warning
id_by_name(UserName('John')) # UserName is ok
name = UserName('John') + 'Smith' # UserName object inherits all parent type methods
Adding type hints
Although PyCharm supports all methods for adding types supported in PEP 484, using type hints through intention actions is the most convenient way. Depending on the interpreter you use, the type is added as an annotation (Python 3) or as a comment (Python 2).
To add a type hint, follow these steps:
- Select a code element.
- Press Alt+Enter.
- Select Add type hint for ....
- Press Enter to complete the action or edit the type if appropriate.
Example | Intention Action | Resulting Code |
---|---|---|
Variables | ||
Functions | ||
Class attributes |
You can also use Python stubs or comments to specify the types of variables, functions, and class fields.
Specifying types by using comments
Use a # type:
comment to specify the types of local variables and attributes:
Python stubs
PyCharm supports Python stub files with the .pyi
extension. These files allow you to specify the type hints using Python 3 syntax for both Python 2 and 3.
The stub files are created as usual, but you must specify the extension .pyi
explicitly.
PyCharm shows an asterisk in the left gutter for those Python files that have stubs:
Clicking the asterisk results in jumping to the corresponding file with the .pyi
extension:
Legacy type syntax for docstrings
PyCharm supports legacy approach to specifying types in Python using docstrings. So doing, the supported formats are:
To choose the desired docstring format, use the Python Integrated Tools page of the Settings/Preferences dialog.
Type syntax in Python docstrings is not defined by any standard. Thus, PyCharm suggests the following notation:
Syntax | Description |
---|---|
Foo | Class Foo visible in the current scope |
x.y.Bar | Class Bar from x.y module |
Foo | Bar | Foo or Bar |
(Foo, Bar) | Tuple of Foo and Bar |
list[Foo] | List of Foo elements |
dict[Foo, Bar] | Dict from Foo to Bar |
T | Generic type (T-Z are reserved for generics) |
T <= Foo | Generic type with upper bound Foo |
Foo[T] | Foo parameterized with T |
(Foo, Bar) -> Baz | Function of Foo and Bar that returns Baz |
list[dict[str, datetime]] | List of dicts from str to datetime (nested arguments) |
Specifying types of local variables
Consider adding information about the expected type of a local variable using :type
or @type
docstrings:
It is also possible to use isinstance
to define the expected local variable type:
Specifying types of fields
You can use type hinting to specify the expected type of fields:
Alternatively, you can specify types of fields in the docstring of a class:
Specifying return types
Use docstrings :rtype
or @rtype
to specify the expected return type:
:rtype: collections.Iterable[int] # return type
: 'items' is of typegenerator
orcollections.Iterable
, 'a' is of typeint
, see the following code:def my_iter(): for i in range(10): yield i items = my_iter() for a in items: print a
- :rtype: list[int] for my_iter # return type: 'a' is of type
int
, see the following code:def my_iter(): for i in range(10): yield i for a in my_iter(): print a
Specifying parameter types
Consider adding information about the expected parameter type. This information is specified using :type
or @type
docstrings, for example, :param "type_name" "param_name": "param_description"
.
Converting comments
For comment-based type hints, PyCharm suggests an intention action that allows you to convert comment-based type hint to a variable annotation. This intention has the name Convert to variable annotation, and works as follows:
Before | After |
---|---|
from typing import List, Optional
xs = [] # type: List[Optional[str]] | from typing import List, Optional
xs: List[Optional[str]] = [] |
Using Typeshed
Typeshed is a set of files with type annotations for the standard Python library and various packages. Typeshed stubs provide definitions for Python classes, functions, and modules defined with type hints. PyCharm uses this information for better code completion, inspections, and other code insight features.
PyCharm is switching to Typeshed, the common repository for Python stubs. The Typeshed stubs bundled with PyCharm are shown in the project view under the node External Libraries | <Python interpreter> | Typeshed Stubs. Note that PyCharm currently uses only a few of the bundled stubs (i.e. builtins.pyi
, typing.pyi
, and several others).
To override the bundled Typeshed repository with your own version, follow these steps:
- Copy some or all the stubs into a directory in your project.
- Mark a directory as a source root by choosing Mark Directory as | Sources Root from the context menu of the directory.
The Python skeletons repository https://github.com/JetBrains/python-skeletons is now deprecated.