2

I have the following nested functions

from typing import Optional

def outer(
    outer_foo:int,
    outer_bar:Optional[int] = 5
):
    return inner(outer_foo, outer_bar)

def inner(
    inner_foo:int,
    inner_bar:int
):
    return inner_foo+inner_bar

print(outer((1)))

and mypy throws the following error:

error: Argument 2 to "inner" has incompatible type "Optional[int]"; expected "int"

given that I gave an int as default value of outer_bar, I don't see a potential issue. However, I was able to solve the mypy error changing the code to this:

from typing import Optional

def outer(
    outer_foo:int,
    outer_bar:Optional[int] = None
):
    if outer_bar is None:
        outer_bar = 5
    return inner(outer_foo, outer_bar)

def inner(
    inner_foo:int,
    inner_bar:int
):
    return inner_foo+inner_bar

print(outer((1)))

Which seems to be defeating the usefulness of default arguments in the declaration. Is this the best/pythonic way to do it?

apocalypsis
  • 520
  • 8
  • 19
  • 1
    `Optional` means it can be `None`. Not that it is a default argument. – Axe319 Jan 10 '22 at 18:37
  • *You* told it the type was `Optional`, which by definition means that it can be `None`. That means if you call `outer` with `outer(1, None)`, that will be valid, but then, there would be an error when that `None` passed to `inner`. – juanpa.arrivillaga Jan 10 '22 at 19:09

1 Answers1

5

As there is a default value, then outer_bar isn't an Optional as it'll not be None

def outer(outer_foo: int, outer_bar: int = 5):
    return inner(outer_foo, outer_bar)

Note, when the default value needs to be a empty list, regarding "Least Astonishment" and the Mutable Default Argument use None as default value, then or []

def outer(outer_foo: int, outer_bar: Optional[list[int]] = None):
    return inner(outer_foo, outer_bar or [])
azro
  • 53,056
  • 7
  • 34
  • 70