在下面的代码中,调用clone()
在 A 的实例上调用该方法将返回 A 类型的实例,在 B 的实例上调用该方法将返回 B 类型的实例,依此类推。目的是创建一个与当前实例相同但具有不同的内部生成主键的新实例,因此可以从那里对其进行编辑并安全地另存为新项目。
???
是某种类型限定符,但我不确定正确的选择是什么。
class A:
def clone(self) -> ???:
cls = self.__class__
result = cls.__new__(cls)
for k, v in self.__dict__.items():
setattr(result, k, deepcopy(v))
result.id = self.__generate_id()
return result
class B(A):
def do_b(self):
pass
我目前更换了???
with 'A'
。这是可行的,但如果我想克隆 B 类型的对象,如果我想在其上调用特定于 B 的方法,则必须转换返回值:
b = B().clone()
b.do_b() # type error!
b = cast(B, B().clone())
b.do_b() # OK
但是,可以保证调用.clone()
类型 B 的对象将返回另一个类型 B 的对象,这对我来说太像 Java 了。是否有一些基于泛型的方法可以告诉 mypy 该方法返回类型的对象__class__
,无论该类是什么?
您可以通过使用来做到这一点具有通用自我的通用方法-- 基本上,注释你的self
变量是通用的:
from typing import TypeVar
T = TypeVar('T', bound='A')
class A:
def __generate_id(self) -> int:
return 0
def clone(self: T) -> T:
cls = self.__class__
result = cls.__new__(cls)
for k, v in self.__dict__.items():
setattr(result, k, deepcopy(v))
result.id = self.__generate_id()
return result
class B(A):
def do_b(self):
pass
reveal_type(A().clone()) # Revealed type is A
reveal_type(B().clone()) # Revealed type is B
基本上,当我们打电话时clone()
, the T
当 mypy 尝试对克隆调用进行类型检查时,typevar 将绑定到当前实例的类型。这最终使返回类型与实例的类型匹配,无论它是什么。
您可能想知道为什么我设置上限T
to A
。这是因为该行self.__generate_id()
。基本上,为了对该行进行类型检查,self
不能是字面上的任何类型:它需要是A
或某些子类A
。界限编码了这一要求。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)