Как мне сообщить MyPy, что параметр не является обязательным?

У меня есть объект src и необязательный объект dest. Если dest не передается в функцию, создается новый MyObj, который передается другой функции.

Использование mypy==0.610 дает мне:

ошибка: аргумент 2 к «copy_data» имеет несовместимый тип «Optional [MyObj]»; ожидается "MyObj"

Как мне сообщить MyPy, что dest не является обязательным в функции copy_data?

from typing import Optional


class MyObj(object):
    def __init__(self, name):
        self.name = name

def new_obj(name):
    # type (str) -> MyObj
    return MyObj(name=name)

def copy_stuff(src, dest=None, fname=None):
    # type: (MyObj, Optional[MyObj], Optional[str]) -> MyObj
    if not dest:
        dest = new_obj(fname)
    my_obj = copy_data(src, dest)
    return my_obj

def copy_data(src, dest):
    # type: (MyObj, MyObj) -> MyObj
    return dest

person Jamie Bull    schedule 11.06.2018    source источник
comment
Возникает ли ошибка, если вы создаете отдельную локальную переменную в copy_stuff для хранения экземпляра MyObj?   -  person BrenBarn    schedule 11.06.2018
comment
Ах, на самом деле он доволен dest = dest or new_obj(fname)   -  person Jamie Bull    schedule 11.06.2018
comment
Мне кажется, это проверка типа. Не могли бы вы предоставить минимально воспроизводимый образец? Какую версию mypy вы используете?   -  person ethanhs    schedule 11.06.2018
comment
@ethanhs Я добавил MVE, который у меня не работает на v0.610   -  person Jamie Bull    schedule 11.06.2018
comment
Почему вы проверяете not dest вместо dest is not None?   -  person MisterMiyagi    schedule 11.06.2018


Ответы (1)


Ошибка здесь в new_obj. В комментарии типа отсутствует двоеточие. Я понял это, вставив в ваш MVE несколько reveal_type:

def new_obj(name):
    # type (str) -> MyObj
    #     ^ ERROR is here
    return MyObj(name=name)

def copy_stuff(src, dest=None, fname=None):
    # type: (MyObj, Optional[MyObj], Optional[str]) -> MyObj
    reveal_type(new_obj)  # E: Revealed type is 'def (name: Any) -> Any'
    if not dest:
        reveal_type(dest)  # Optional[MyObj]
        dest = new_obj(fname)
        reveal_type(dest)  # Optional[MyObj]
    my_obj = copy_data(src, dest)
    return my_obj

Mypy, похоже, сохраняет тип Optional[MyObj] при назначении из функции, возвращающей Any. Если комментарий к типу исправлен, он работает должным образом.

person ethanhs    schedule 11.06.2018
comment
Это кажется правильным и определенно исправляет MVE. Я все еще удивляюсь, почему он работает с dest = dest or new_obj(fname), хотя - person Jamie Bull; 11.06.2018
comment
Потому что, если dest не None, он будет оцениваться как dest, если это так, первая часть выражения оценивается как ложная, поэтому вторая часть выражения, new_obj(fname), передается. Поскольку это имеет тип Any, это принято. - person ethanhs; 12.06.2018