检查类中的字段是否为键入的最佳方法是什么?可选?
示例代码:
from typing import Optional
import re
from dataclasses import dataclass, fields
@dataclass(frozen=True)
class TestClass:
required_field_1: str
required_field_2: int
optional_field: Optional[str]
def get_all_optional_fields(fields) -> list:
return [field.name for field in fields if __is_optional_field(field)]
def __is_optional_field(field) -> bool:
regex = '^typing.Union\[.*, NoneType\]$'
return re.match(regex, str(field.type)) is not None
print(get_all_optional_fields(fields(TestClass)))
其中fields
来自dataclasses
,我想列出所有Optional
字段。我现在解决这个问题的方法是使用基于Regex的字段名,但我不喜欢这种方法。有没有更好的办法呢?
6条答案
按热度按时间58wvjzkj1#
作为参考,Python 3.8(2019年10月首次发布)在
typing
模块中添加了get_origin
和get_args
函数。文档中的示例:
这将允许:
对于较旧的Python,这里有一些兼容性代码:
dgsult0t2#
注意:
typing.Optional[x]
是typing.Union[x, None]
的别名现在,可以检查输入字段注解的属性,检查它是否像Union[x,None]那样定义:
您可以读取其属性
__module__
、__args__
和__origin__
:您需要执行以下步骤来定义检查器:
1.确保注解具有键
__module__
、__args__
和__origin__
__module__
必须设置为“typing”。如果不是,则注解不是由类型化模块定义的对象__origin__
值等于键入。Union__args__
必须是一个包含2个元素的元组,其中第二个元素是类NoneType(type(None)
)如果所有条件的计算结果都为true,则表示您已键入。可选[x]
您可能还需要知道注解中的可选类是什么:
uurity8g3#
另一种方法(适用于python 3.7和3.8)是中继
Union
操作的工作方式:union([x,y],[y])= union([x],[y]) = union(union([x],[y]),[x,y])
逻辑是
Optional
类型不能是Optional
er。虽然你不能直接知道type
是否是空的/可选的,但Optional[type]
将与type
相同,type
是可选的,其他(确切地说是Union[type,None]
)。因此,在我们的案例中:
(the第一个等于
Optional[SomeType]
,第二个等于Optional[Optional[SomeType]]
这样可以很容易地检查
Optional
值:gv8xihay4#
Optional[X]
等于Union[X, None]
。所以你可以,zlhcx6iw5#
Python 3.10添加了符号
T | None
来指定联合类型(参见PEP 604)。在我的本地Python 3.10.7中,types.get_origin
将其转换为types.UnionType
(而不是`typing.Union)。所以下面的代码适用于平面联合(但请参阅SimSimY关于嵌套联合的答案)。这是一个测试:
xsuvu9jc6#
我写了一个叫做typedload的库,可以用来做这个。
该库的主要目的是转换为/从json和namedtuple/dataclass/attrs,但由于它需要做这些检查,它公开了函数。
请注意,不同版本的python会改变内部类型API的工作方式,因此检查不会在每个python版本上工作。
我的库在内部解决它,向用户隐藏细节。
使用它,代码是这样的
https://github.com/ltworf/typedload
当然,如果你不需要支持多个python版本,你可能不需要依赖一个库,但是未来的版本可能会打破这个检查。他们甚至在小版本之间改变了API。