Does PEP 484 allow mixing of type comments and annotations?

I have seen mention somewhere (I don’t remember where) that PEP 484 does not allow type comments that conflict with function argument annotations. That is, you cannot have

def f(x: int) -> str: # type: (int) -> str

I don’t find anything in PEP 484 that addresses this case.

My question is: how should a type checker treat this? What if the types are different (that is, type: (bool) -> str or type: (int) -> bool)? Should type comments and annotations even be allowed in the same module at all?

My own opinion is that when a function has a type comment, with argument types (including type: () -> str), then there can be no annotations on any of the arguments. Furthermore, even with type: (...) -> str, there can be no return annotation. Any violation of this should be reported as an error.

I haven’t consciously noticed code that had both in one place, but I agree, it doesn’t make sense to have both. I’d probably just ignore the comment entirely if any actual annotations were seen from a type checker POV, but that isn’t super helpful towards improving the code. It’d be nice to warn the user about it. It isn’t technically in error unless the type signature disagrees but I doubt it is worth the time to implement such an agreement checker.

If someone can come up with examples of this happening in a bad way in code often enough, maybe that assumption of not being worth it is wrong.

Current sentiment looks to be a deprecation process (timeline unclear though). The primary motivation for type comments was python 2. As python 2 has been EOL for some time I don’t think new rules/checks involving type comments are likely.


Personally I feel detecting this and warning the user is better suited for tools like pyflakes instead of a type checker.

1 Like

Better yet, just run com2ann and whatever type comments you have will be automatically translated to annotations :sparkles:. You might need to fix up some imports if they weren’t quite valid as static types, but that’s all it takes!

(other great tools for upgrading old code: modernize and pyupgrade, applied in that order)