Python中用于(任意)类的类型提示

29

我想对以下函数使用类型提示:

def get_obj_class(self) -> CLASS_TYPE:
  return self.o.__class__
  • CLASS_TYPE应表示class
  • self.o可以是在运行时确定的任何类型。

同样地,如果我有一个函数f(cls: CLASS_TYPE),它返回cls的实例,是否有一种方式适当地对返回值进行类型提示?

3个回答

21

我建议采用TypeVar的组合,以表示您的self.o值可以是任意类型,并采用以下方式使用Type

from typing import TypeVar, Type

T = TypeVar('T')

class MyObj:
    def __init__(self, o: T) -> None:
        self.o = o

    def get_obj_class(self) -> Type[T]:
        return type(self.o)

def accept_int_class(x: Type[int]) -> None:
    pass

i = MyObj(3)
foo = i.get_obj_class()
accept_int_class(foo)    # Passes

s = MyObj("foo")
bar = s.get_obj_class()
accept_int_class(bar)    # Fails

如果你想让变量 o 的类型更加动态,你可以显式或隐式地将其类型指定为 Any
关于你后面的问题,你可以这样做:
def f(cls: Type[T]) -> T:
    return cls()

请注意在实例化类时需要小心 - 我不记得Pycharm 在这里做了什么,但我知道目前mypy不会检查您是否正确地调用了您的__init__函数/使用了正确数量的参数。这是因为T可以是任何东西,但没有办法提示构造函数应该看起来像什么,因此执行此检查将变得非常困难或者几乎不可能。

4
我很不喜欢每次想构建自定义类型时都需要创建一个带名称的TypeVar对象。在我的情况下,我更倾向于使用type。但是感谢您介绍这个。 - yspreen
1
@nO_OnE_910 -- 当你定义通用类和函数时,可以重复使用相同的TypeVar变量。也许你会发现这样做会更加舒适,因为你只需要引入一个命名的TypeVar对象(然后重复使用它),而不是每个通用类或函数都需要一个。 - Michael0x2a

15

对于Python >=3.7,使用type(还可以参考PEP 585):

def get_obj_class(self) -> type:
    return self.o.__class__

对于Python <3.7,使用typing.Type

def get_obj_class(self) -> typing.Type:
    return self.o.__class__

2
为了简单起见,尽管typing.TypeVar似乎是正确的解决方案 - yspreen

1

typing.Type 呢?

看起来很合适,因为 __class__ 应该始终返回一个类型。

import typing

def test(t: object) -> typing.Type:
    return t.__class__

class Dummy(object):
    pass

test(Dummy())

对于你的第二个问题:那应该是一个通用链接。

为什么使用 typing.Type 而不是 type - yspreen
1
@nO_OnE_910 我更喜欢使用typing模块来保持一致的风格。我的大多数返回值都是typing.X,所以对我来说似乎更自然。 - Christian Sauer

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