Python:编写一个通用函数,它接收一个类型并返回该类型的实例化对象

10
我想给一个接收类型作为参数的Python函数添加类型注释(实际上是特定类的子类型),并返回该类型的实例。可以将其视为以特定类型作为参数的工厂函数,例如:
T = TypeVar('T', bound=Animal)

def make_animal(animal_type: Type[T]) -> T:  # <-- what should `Type[T]` be?
    return animal_type()

(显然这只是一个非常简单的例子,但它说明了这种情况)
这似乎应该是可能的,但我找不到如何正确地为其添加类型提示的方法。

2个回答

11

不确定你的问题是什么,你发布的代码是完全有效的Python代码。typing.Type 正好可以实现你想要的功能:

from typing import Type, TypeVar

class Animal: ...
class Snake(Animal): ...

T = TypeVar('T', bound=Animal)

def make_animal(animal_type: Type[T]) -> T:
    return animal_type()

reveal_type(make_animal(Animal))  # Revealed type is 'main.Animal*'
reveal_type(make_animal(Snake))   # Revealed type is 'main.Snake*'

查看在 mypy-play 上的 mypy 输出。


我不确定为什么我错过了那个,谢谢。 - shevron
我想唯一可能会棘手的是要知道在 make_animal(Snake) 中,类型变量 T 推断为 Snake 而不是 Animal - Andrew
请注意,只要任何一个类具有@abstractmethod修饰符,此功能将停止工作。 - undefined
@Sigmatics 你能详细解释一下吗?如果类中存在未重写的抽象方法,那么是的,这将导致类型错误,但这是因为构造抽象类的对象是不正确的。如果 Animal 是抽象的,但 Snake 不是,那么 make_animal(Snake) 仍然可以通过类型检查。 - undefined
@Andrew没错。虽然我认为,如果你真的想让它是Animal,你应该将其注释为type[Animal]。如果在AnimalSnake之间还有其他类别,那么返回中间的任何内容都是不明确的。 - undefined

-1

这样怎么样?

from __future__ import annotations
from typing import Type


class Animal:
    ...


def make_animal(animal_type: Type[Animal]) -> Animal:
    return animal_type()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接