Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python typehints and linters

I've been adding static typechecking to our python project, for example like this:

from typing import List
from something import MyOtherClass

class MyClass:
    def __init__(self) -> None:
        self.some_var = None  # type: List[MyOtherClass]

However, now the linters we use (flake8 and pylint) report for example List as unused variables, since they are not used in actual code. (pep8 handles it fine, by the way).

So we end up changing the code to this:

from typing import List  # noqa # pylint: disable=unused-import
from something import MyOtherClass  # noqa # pylint: disable=unused-import

class MyClass:
    def __init__(self) -> None:
        self.some_var = None  # type: List[MyOtherClass]

Is there any better solution to solve this? We don't want to disable all unused import warnings.

like image 941
tobspr Avatar asked Nov 24 '16 08:11

tobspr


People also ask

What are Python linters?

Linters are programs that advise about code quality by displaying warnings and errors. They can detect your Python code mistakes, notice invalid code patterns and find elements that do not follow your conventions. Python linters have a number of advantages, such as: Preventing bugs in a project.

What do type hints do in Python?

Type hints improve IDEs and linters. They make it much easier to statically reason about your code. Type hints help you build and maintain a cleaner architecture. The act of writing type hints forces you to think about the types in your program.

Does Python enforce type hints?

Python will always remain a dynamically typed language. However, PEP 484 introduced type hints, which make it possible to also do static type checking of Python code. Unlike how types work in most other statically typed languages, type hints by themselves don't cause Python to enforce types.

What Linter should I use for Python?

PEP8 is a great starting point for Python. Linters will help you identify problem areas and inconsistencies. You can use linters throughout the development process, even automating them to flag lint-filled code before it gets too far.


2 Answers

Python 3.6 implements PEP 526: Syntax for Variable Annotations, which as the name suggests introduces new syntax for variable annotations, removing the need for type comments.

In the new syntax, your code would be rewritten as:

from typing import List, Optional
from something import MyOtherClass

class MyClass:

    def __init__(self) -> None:
        self.some_var: Optional[List[MyOtherClass]] = None

... or alternatively:

from typing import List, Optional
from something import MyOtherClass

class MyClass:

    some_var: Optional[List[MyOtherClass]]

    def __init__(self) -> None:
        self.some_var = None

Since List and MyOtherClass now appear as actual tokens in the code, rather than comments, linters should have no trouble acknowledging that they are indeed being used.

like image 140
Zero Piraeus Avatar answered Oct 03 '22 06:10

Zero Piraeus


@Zero Piraeus answer offers the most recent solution to this (i.e use variable annotations, also see: What are variable annotations in Python 3.6?).

Apart from that, you don't even need to import List when you're using # type: comments. mypy doesn't require them to be imported and neither to pyflakes or pylint as far as I am aware.

There's no need to import names from typing unless you require to use their name somewhere that Python actually performs a name look-up (and in comments, this isn't required.)

like image 30
Dimitris Fasarakis Hilliard Avatar answered Oct 03 '22 08:10

Dimitris Fasarakis Hilliard