从类型到实例化对象的 Python 通用类型提示

Posted

技术标签:

【中文标题】从类型到实例化对象的 Python 通用类型提示【英文标题】:Python Generic typehint going from type to instanciated object 【发布时间】:2021-09-28 20:19:02 【问题描述】:

我的 IDE 自动完成目前存在一些问题,因为它无法判断返回类型是什么等。

我有一个单例元类,覆盖类似于此的 __call__ 方法:

SingletonTypes = typing.TypeVar("SingletonTypes")


class Singleton(ABCMeta):
    def __call__(cls: SingletonTypes, environment: str = None, *args, **kwargs) -> SingletonTypes:
        /* code here, will return an instanciated copy of cls */
        return super(Singleton, cls).__call__()

我的问题是如果我有通用类型提示,显然 cls 是一种类型,它会返回对象。我不确定如何指定 typehints 来表明这一点,而没有 python 会感到困惑。

如果我尝试将type(SingletonTypes) 添加到 cls 类型提示中,那么它不会提出任何建议,因为 SingletonType 之间没有一致性。不太确定如何进行,如果能正常使用自动完成功能会很好。

【问题讨论】:

【参考方案1】:

你试过了吗:

def __call__(cls: Singleton, environment: str = None, *args, **kwargs) -> SingletonTypes:

从技术上讲,这是正确的:cls 是“Singleton”的一个实例,它是您的单例类的元类。但我不确定围绕注释的工具对元类的工作方式有多了解——在某些方面,用于类型提示和注释的工具感觉与语言的实际工作方式完全脱节。

如果这不起作用,您应该满足于使用单例而不求助于元类,因为无论如何这都是多余的。除非您需要一个只运行一次的 __init__ 方法,并且不能在 __new__ 中,否则您只需将在元类中的相同逻辑添加到 __call__ 到类上的 __new__ ,或在基类本身上。由于这种机制将使用简单的继承,类型提示机制应该可以正常工作,不需要特殊的注释:

class SingletonBase:
    def __new__(cls, *args, **kw):
         if "_instance" in cls.__dict__:
             return cls._instance  # NB: this will still trigger a call to __init__ in subclasses
         instance = super().__new__(cls, *args, **kw)
         cls._instance= instance
         return instance

(我认为在这种情况下,类型提示机制甚至可以在没有显式注释的情况下找到自己的方式,因为__new__ 的角色在语言语义中得到了很好的定义)

【讨论】:

我刚刚试了一下,又不行了。我认为问题在于 SingletonTypes 是泛型的,python 没有关于实际输出的信息,因为它通常来自泛型参数。

以上是关于从类型到实例化对象的 Python 通用类型提示的主要内容,如果未能解决你的问题,请参考以下文章

返回非实例化类类型的类型提示[重复]

C++从青铜到王者第六篇:C++模板初阶

打字稿:如何将对象映射到类型?

模板之类模板

Chapter16:模板

为啥我的通用服务出现“无法实例化实现类型”错误?