python 加引号的 typing hint 是怎么回事?

pydantic/main.py

@classmethod
def from_orm(cls: Type['Model'], obj: Any) -> 'Model':
    if not cls.__config__.orm_mode:
        raise ConfigError('You must have the config attribute orm_mode=True to use from_orm')
    obj = {ROOT_KEY: obj} if cls.__custom_root_type__ else cls._decompose_class(obj)
    m = cls.__new__(cls)
    values, fields_set, validation_error = validate_model(cls, obj)
    if validation_error:
        raise validation_error
    object_setattr(m, '__dict__', values)
    object_setattr(m, '__fields_set__', fields_set)
    m._init_private_attributes()
    return m

看 pydantic 的时候,发现 Type['Model'] 这种东西,用引号括起来这样 Model 不是从一个 class 变成 str 了吗?

关键是,vscode 还能正常提供代码智能提示

图片.png

什么原理?哪个 PEP 里面有说明?

为什么要加引号?是为了兼容低版本的 python 吗?比如兼容 python3.6 ?

阅读 3.4k
2 个回答

有些类型标注在使用时其实还未被完全定义,这是不能直接使用这个标识符。这个时候就可以使用字符串。

比如你的 Model ,需要等 Model 类结束才被完全定义,在其方法的参数的类型标注里就无法被直接使用。所以要使用字符串。

参见:https://peps.python.org/pep-0...

When a type hint contains names that have not been defined yet, that definition may be expressed as a string literal, to be resolved later.

另外,根据 PEP563 ,以后标注无论写成什么形式,实际都是一个字符串,然后再延迟计算。这样就可以不用 "Model" ,而是直接写 Model 。因为此时已经不再需要 Model 是一个已经定义的标识符了。以后再需要使用这个个类型标注的时候,需要通过这个字符串重新求值,得到实际的标注类型,而此时通常类已经有完整定义了。

可以通过 from __future__ import annotations 提前启用这一功能。

类似反射..会通过这个字符串去查找对应的类型,常常用于类型没有被定义的情况

这种情况下,A在定义的时候还不认识B...所以用'B'替代
class A:
    def __init__(self,b:'B')
        pass

class B:
    pass
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题