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

Kam*_*yar 20 python python-dataclasses

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

from dataclasses import dataclass

@dataclass
class MyClass:
    id: int = 0
    name: str = ''
Run Code Online (Sandbox Code Playgroud)

在函数参数中使用类型提示(注释)时,可以使用inspect模块轻松获取带注释的类型.如何获取dataclass字段类型?

use*_*ica 15

检查__annotations__为您提供原始注释,但这些注释不一定对应于数据类的字段类型.像ClassVar和InitVar这样的东西出现了__annotations__,即使它们不是字段,并且继承的字段也不显示.

而是调用dataclasses.fields数据类,并检查字段对象:

field_types = {field.name: field.type for field in fields(MyClass)}
Run Code Online (Sandbox Code Playgroud)

__annotations__不会也fields不会解决字符串注释.如果要解析字符串注释,最好的方法可能就是typing.get_type_hints.get_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}
Run Code Online (Sandbox Code Playgroud)


Ser*_*tar 14

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)}
Run Code Online (Sandbox Code Playgroud)

在旁注中还有:

myclass.__dataclass_params__
>>_DataclassParams(init=True,repr=True,eq=True,order=False,unsafe_hash=False,frozen=False)
Run Code Online (Sandbox Code Playgroud)

  • 这里要注意,如果您不是在 3.10 上并使用“from __future__ import 注解”,则“type”字段将是类型的“str”表示,而不是“type”本身。 (9认同)
  • 作者把工作放在格式化问题的正确答案中。您能否指出一些不鼓励编写与评论重叠的答案的文档? (2认同)
  • 我宁愿不使用这样的私有字段。我需要类似检查模块签名对象的东西。 (2认同)
  • @WolfgangPfnür 同样在这里,救星评论。这是一个极其令人讨厌的“功能”。 (2认同)

And*_*yko 5

dataclasses.py是提供装饰器和函数的模块,用于使用字段注释生成常规类方法。这意味着在处理类之后,应使用PEP 526 变量注释语法形成用户定义的字段。模块注释可以通过.__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)
Run Code Online (Sandbox Code Playgroud)