Mypy: Infer argument type from default value

Created on 30 Mar 2017  路  5Comments  路  Source: python/mypy

def test(x:int, y=5):
    reveal_type(y)

This currently reveals the type as Any. I propose it should use the type inference instead and consider this int.
Perhaps making it optional with a flag, but this seems reasonable to me. I had actually assumed it already worked like this until I decided to verify just now.
It is kind of like initialising the variable, is it not?

Most helpful comment

OTOH most of those also apply to regular assignments, and there the rule is that

x = 0

infers type int for x. In practice this is very common and useful and only occasionally needs help. So I think we might use the same rule for default values and the complexity of explaining things wouldn't really change. I'm willing to make this a PEP 484 change if enough people care.

All 5 comments

You may have a point. Can you try to find if PEP 484 says it has to be one way or another? If it doesn't we should clarify this there, and if it doesn't we may have to have a larger discussion about whether to change this.

I couldn't find anything about default arguments explicitly, but in The Any Type, it does say "A function parameter without an annotation is assumed to be annotated with Any."

I don't know much about how python and its ecosystem is developed - I only use it at work. This is just something I noticed and would prefer to work differently.

I expect @JukkaL can explain the current policy better.

Mypy follows PEP 484. A function parameter without an annotation is the same as having an Any annotation, and there is no exception for default values. Here is some rationale for this:

  • Often the default argument is not enough to infer a type. For example, None doesn't give enough context. With the current rules this doesn't pose a difficulty.
  • The default argument may not be enough to infer the correct type. For example, if the default is '' in Python 2, the correct type could well be Union[str, unicode]. If the default is 0, the correct type might well be float. If the programmer understands the rules for type inference they could override the default type with an annotation as needed, but this would add some extra complexity.
  • The default value could be a complex expression such as a function call, and thus the type may not obvious from just the default value. Having an annotation makes code like this easier to read.
  • If a function has no annotation at all, then the argument type would have to be Any anyway. The current rule makes this consistent across functions with no annotations and functions with partial annotations.

It all boils down to the current rule being simple and obvious, and in practice it doesn't feel much of a burden to add a few extra : int annotations. There is no deep technical reason for the current rule, though it makes type inference easier for mypy.

OTOH most of those also apply to regular assignments, and there the rule is that

x = 0

infers type int for x. In practice this is very common and useful and only occasionally needs help. So I think we might use the same rule for default values and the complexity of explaining things wouldn't really change. I'm willing to make this a PEP 484 change if enough people care.

Was this page helpful?
0 / 5 - 0 ratings