如何获得 Python 3.7 新的数据类字段类型?

Posted

技术标签:

【中文标题】如何获得 Python 3.7 新的数据类字段类型?【英文标题】:How can I get Python 3.7 new dataclass field types? 【发布时间】:2019-01-27 12:25:20 【问题描述】:

Python 3.7 引入了称为数据类的新功能。

from dataclasses import dataclass

@dataclass
class MyClass:
    id: int = 0
    name: str = ''

在函数参数中使用类型提示(注解)时,您可以使用检查模块轻松获取注解类型。如何获取数据类字段类型?

【问题讨论】:

我宁愿不使用这样的私有字段。还是谢谢 这不是私有字段。此外,您刚刚接受了一个使用“dunder”属性的答案。 顺便说一句,get_type_hints 是推荐的选项,而不是__annotations__ 【参考方案1】:

检查__annotations__ 会为您提供原始注释,但这些注释不一定对应于数据类的字段类型。 ClassVar 和 InitVar 之类的东西会出现在 __annotations__ 中,即使它们不是字段,继承的字段也不会出现。

相反,在数据类上调用dataclasses.fields,并检查字段对象:

field_types = field.name: field.type for field in fields(MyClass)

__annotations__fields 都不会解析字符串注释。如果要解析字符串注解,最好的办法大概是typing.get_type_hintsget_type_hints 将包括 ClassVars 和 InitVars,因此我们使用 fields 将它们过滤掉:

resolved_hints = typing.get_type_hints(MyClass)
field_names = [field.name for field in fields(MyClass)]
resolved_field_types = name: resolved_hints[name] for name in field_names

【讨论】:

补充一点,数据类支持继承,但__annotations__ 不会解析父类中的字段【参考方案2】:
from dataclasses import dataclass

@dataclass
class MyClass:
    id: int = 0
    name: str = '' 

myclass = MyClass()

myclass.__annotations__
>> 'id': int, 'name': str
myclass.__dataclass_fields__
>> 'id': Field(name='id',type=<class 'int'>,default=0,default_factory=<dataclasses._MISSING_TYPE object at 0x0000000004EED668>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy(),_field_type=_FIELD),
 'name': Field(name='name',type=<class 'str'>,default='',default_factory=<dataclasses._MISSING_TYPE object at 0x0000000004EED668>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy(),_field_type=_FIELD)

另外还有:

myclass.__dataclass_params__
>>_DataclassParams(init=True,repr=True,eq=True,order=False,unsafe_hash=False,frozen=False)

【讨论】:

作者将作品放入以格式化问题的正确答案。您能否指出一些不鼓励编写与 cmets 重叠的答案的文档? 我宁愿不使用这样的私有字段。我需要像检查模块签名对象这样的东西。 请注意,如果您不在 3.10 上并使用 from __future__ import annotationstype 字段将是该类型的 str 表示形式,而不是 type 本身。 @WolfgangPfnür 谢谢你的评论,我现在一直被这个问题困扰,想知道为什么所有的答案都是“不正确的”。【参考方案3】:

dataclasses.py是通过使用字段注释提供用于生成常规类方法的装饰器和函数的模块。这意味着在处理类之后,用户定义的字段应使用PEP 526 Syntax of Variable annotations形成。模块注释可通过__annotations__ 访问。

根据Runtime effects of type annotations,注释类型可通过__annotations__ 属性或使用typing.get_type_hints(推荐的最后一种)访问。

请看下面的一些代码示例:

from typing import Dict, ClassVar, get_type_hints
from dataclasses import dataclass

@dataclass
class Starship:
    hitpoints: int = 50


get_type_hints(Starship) // 'hitpoints': int
Starship.__annotations__ // 'hitpoints': int
dataclasses.__annotations__ // The annotations of the dataclasses module.
get_type_hints(get_type_hints)

【讨论】:

以上是关于如何获得 Python 3.7 新的数据类字段类型?的主要内容,如果未能解决你的问题,请参考以下文章

获得mysql数据库信息 (字段名字段类型字段注释)工具类

如何在 Python 3.7 中快速并行化函数?

sqlserver 如何获得所有数据库名 如何获得已知数据库所有表名 和 已知表明获得所有字段名和字段类型

Python 3.7 / Django 2.2.1:保存前检查字段

Windows 7(64 位)上的 Python 3.7 64 位:CSV - 字段大于字段限制(131072)[重复]

sql如何获得某个数据库里面的表的字段名,字段类型,字段长度(sql server2005)