为什么我需要转换 copy.deepcopy 的结果?

问题描述

这是我为玩具类重载 __deepcopy__ 的尝试

import copy
from typing import Dict

class Foo:
    pass


class Bar:
    def __init__(self,foo: Foo):
        self._foo = foo

    def __deepcopy__(self,memo: Dict[int,object]) -> Bar:
        return Bar(copy.deepcopy(self._foo,memo))

然而,mypy 抱怨

错误:“Bar”的参数 1 具有不兼容的类型“object”;预期的“Foo”

我可以通过转换 copy.deepcopy

的结果来修复它
from typing import cast

    ...
    def __deepcopy__(self,object]) -> Bar:
        return Bar(cast(Foo,copy.deepcopy(self._foo,memo)))

但这感觉没有必要。我这样做对吗?

编辑:我刚刚挖掘了 typeshed repo,发现他们确实输入了

_T = TypeVar("_T")

def deepcopy(
    x: _T,memo: Optional[Dict[int,Any]] = ...,_nil: Any = ...
) -> _T: ...

我认为应该可以防止需要 cast

解决方法

deepcopy 的类型签名是对的

def deepcopy(x: _T,memo: Optional[Dict[int,Any]] = ...,_nil: Any = ...) -> _T: ...

将避免强制转换结果。

但是,这在 5 天前已在 https://github.com/python/typeshed/pull/4828 中修复。

因此,mypy 没有使用该类型定义,而是使用签名:

def deepcopy(x: _T,_T]] = ...,_nil: Any = ...) -> _T: ...

您有 3 个选择:

  • 在此期间继续使用演员表
  • 克隆最新版本的 typeshed 并使用配置选项 custom_typeshed_dir
  • memo 的类型更改为 Dict[int,Foo]

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...