Python type hinting without cyclic imports

python, python-3.4, python-3.5, python-typing, type-hinting

Solution

There isn't a hugely elegant way to handle import cycles in general, I'm afraid. Your choices are to either redesign your code to remove the cyclic dependency, or if it isn't feasible, do something like this:

# some_file.py

from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from main import Main

class MyObject(object):
    def func2(self, some_param: 'Main'):
        ...

The `TYPE_CHECKING` constant is always `False` at runtime, so the import won't be evaluated, but mypy (and other type-checking tools) will evaluate the contents of that block.

We also need to make the `Main` type annotation into a string, effectively forward declaring it since the `Main` symbol isn't available at runtime.

If you are using Python 3.7+, we can at least skip having to provide an explicit string annotation by taking advantage of PEP 563:

# some_file.py

from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from main import Main

class MyObject(object):
    # Hooray, cleaner annotations!
    def func2(self, some_param: Main):
        ...

The `from __future__ import annotations` import will make all type hints be strings and skip evaluating them. This can help make our code here mildly more ergonomic.

All that said, using mixins with mypy will likely require a bit more structure then you currently have. Mypy recommends an approach that's basically what `deceze` is describing -- to create an ABC that both your `Main` and `MyMixin` classes inherit. I wouldn't be surprised if you ended up needing to do something similar in order to make Pycharm's checker happy.

Problem

I'm trying to split my huge class into two; well, basically into the "main" class and a mixin with additional functions, like so: `main.py` file: ``` import mymixin.py class Main(object, MyMixin): def func1(self, xxx): ... ``` `mymixin.py` file: ``` class MyMixin(object): def func2(self: Main, xxx): # <--- note the type hint ... ``` Now, while this works just fine, the type hint in `MyMixin.func2` of course can't work. I can't import `main.py`, because I'd get a cyclic import and without the hint, my editor (PyCharm) can't tell what `self` is. I'm using Python 3.4, but I'm willing to move to 3.5 if a solution is available there. Is there any way I can split my class into two files and keep all the "connections" so that my IDE still offers me auto-completion and all the other goodies that come from it knowing the types?

Original source