Is there a function in the standard library to query whether the type hint for a field admits the None value?
For example, it would return True for foo, bar, baz, and False for x, in class A below:
from dataclasses import dataclass
from typing import Optional, Union
@dataclass
class A:
foo : Optional[int] = None
bar : int|None = None
baz : Union[int, float, None] = None
x : int = 1
I have written the following function, which seems to work, but I want to avoid reimplementing standard functionality.
import typing
import types
def field_is_optional(cls: type, field_name: str):
"""A field is optional when it has Union type with a NoneType alternative.
Note that Optional[] is a special form which is converted to a Union with a NoneType option
"""
field_type = typing.get_type_hints(cls).get(field_name, None)
origin = typing.get_origin(field_type)
#print(field_name, ":", field_type, origin)
if origin is typing.Union:
return type(None) in typing.get_args(field_type)
if origin is types.UnionType:
return type(None) in typing.get_args(field_type)
return False
a=A()
assert field_is_optional(type(a), "foo")
assert field_is_optional(type(a), "bar")
assert field_is_optional(type(a), "baz")
assert field_is_optional(type(a), "x") == False
An acceptable answer will be "No." or "Yes, the function is <function name>
. As @metatoaster pointed out, Check if a field is typing.Optional asks a related question, however (1) it is specific to typing.Optional
not any type that expresses optionality (e.g. Union[int, float, None]
, Union[int, Union[float, None]
, int|float|None
, etc.), and (2) it is asking for any way at all to check (which I already have), whereas I am asking for the name of a single standard library function that does the job.