What is the best way to check if a field from a class is typing.Optional?
Example code:
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)))
Where fields
is from dataclasses
, I wanna list all the Optional
fields.
What I'm doing at this moment to solve it, is using a Regex-based on the field name, but I don't like this approach. Is there a better way of doing it?
For reference, Python 3.8 (first released October 2019) added get_origin
and get_args
functions to the typing
module.
Examples from the docs:
assert get_origin(Dict[str, int]) is dict
assert get_args(Dict[int, str]) == (int, str)
assert get_origin(Union[int, str]) is Union
assert get_args(Union[int, str]) == (int, str)
This will allow:
def is_optional(field):
return typing.get_origin(field) is Union and \
type(None) in typing.get_args(field)
For older Pythons, here is some compatibility code:
# Python >= 3.8
try:
from typing import Literal, get_args, get_origin
# Compatibility
except ImportError:
get_args = lambda t: getattr(t, '__args__', ()) \
if t is not Generic else Generic
get_origin = lambda t: getattr(t, '__origin__', None)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With