python-3.x 如何键入hint一个返回当前类示例的函数?

tktrz96b  于 2023-08-08  发布在  Python
关注(0)|答案(3)|浏览(110)

假设我有这些类:

class GenericCopyable:
    def copy(self) -> GenericCopyable:
        ... # whatever is required to copy this

class CopyableFoo(GenericCopyable):
    ... # uses the parent implementation of "copy"
    def bar(self): …

def some_code(victim: CopyableFoo):
    v = victim.copy()
    v.bar()  ### I know that this works because "v" is a CopyableFoo, but mypy doesn't

字符串
问题是,我需要CopyableFoo.copy()的返回类型是CopyableFoo,而不是GenericCopyable
这可能吗?
编辑:上面是示例代码来说明问题。在这个例子中,以某种方式修改some_codeCopyableFoo当然是可能的;在我的“真实的”程序中,那就更难了。

h7wcgrx3

h7wcgrx31#

你能做到的

from typing import TypeVar
# We define T as a TypeVar bound to the base class GenericCopyable
T = TypeVar('T', bound='GenericCopyable')

class GenericCopyable:
    # we return the type T of the type of self
    # Basically returning an instance of the calling
    # type's class
    def copy(self: T) -> T:
        return type(self)()

class CopyableFoo(GenericCopyable):
    pass

foo = CopyableFoo()

bar = foo.copy()
print(bar)

字符串
这看起来有点笨拙,因为通常我们不需要注解self,因为它隐式地是它绑定到的类的类型。不过,我的意思是,我似乎可以接受它。

ippsafx7

ippsafx72#

一个可能的解决方案是覆盖子类中的方法,然后调用超类方法,子类方法指定其自己示例的返回类型。

class GenericCopyable:
    def copy(self) -> GenericCopyable:
        ... # whatever is required to copy this

class CopyableFoo(GenericCopyable):
   def copy(self)->CopyableFoo:
       return super().copy()

字符串
另一种可能的解决方案是使用类型化模块导入Union。这指定父类中的函数能够返回多个类型

from typing import Union

class GenericCopyable:
    def copy(self) -> Union[GenericCopyable,CopyableFoo]:
        ... # whatever is required to copy this

class CopyableFoo(GenericCopyable):
    #Call parent class method directly
    GenericCopyable.copy()

fsi0uk1n

fsi0uk1n3#

从Python 3.11开始,标准库包含了一个显式的特殊类型- Self。
这取代了@Axe319的answer中建议的TypeVar方法-请注意,上面引用的文档明确提到了这一点。
带有Self的基类应该这样写:

from typing import Self

class GenericCopyable:
    def copy(self) -> Self:
        ...

字符串
这向类型检查器指定GenericCopyable的任何示例从其copy()方法返回与其自身相同类型的示例。

相关问题