0

Is it possible to check the parameter type hint at run time? I would like to use the Python dataclasses in a similar fashion to a Scala case class with pureconfig and HOCON config file. That is, I want to have some optional parameters but would need to check them in another class constructor. However, I dont see how I can get if a param is optional.

from dataclasses import dataclass
from typing import Optional

@dataclass
class Params:
    x: int
    y: int
    z: Optional[int] = None


params = Params(x=2, y=3)

Let's say I want to use the dataclass Params somewhere. If I check z, I will get a NoneType. Maybe I can by pass any errors if I know this by design.

# just some example code 
if z is None and z is not Optional (not sure if or how to check this):
    raise ValueError("z must be specified as an integer")

if z is None and z is optional:
    return x ** 2 + y ** 2
elif z is not None:
    return x ** 2 + y ** 2 + z ** 2
dustin
  • 4,309
  • 12
  • 57
  • 79
  • 1
    Does this answer your question? [How to get class variables and type hints?](https://stackoverflow.com/questions/52838204/how-to-get-class-variables-and-type-hints) – mkrieger1 Aug 23 '21 at 08:36
  • @mkrieger1 thanks. I will take a look at this in detail tomorrow. – dustin Aug 23 '21 at 09:13

1 Answers1

1

See below. The idea is to use __post_init__ and check the annotations of z. Uncomment #z: int and see how it works.

from dataclasses import dataclass
from typing import Optional


@dataclass
class Params:
    x: int
    y: int
    z: Optional[int] = None
    #z: int

    def __post_init__(self):
        print('post init')
        if self.z is None:
            z_annotation = self.__annotations__['z']
            none_is_ok = False
            args = z_annotation.__dict__.get('__args__')
            if args is not None:
                for entry in args:
                    none_is_ok = entry == type(None)
                    if none_is_ok:
                        break
            if not none_is_ok:
                raise ValueError('z can not be None')


p: Params = Params(3, 5, None)
print(p)
balderman
  • 22,927
  • 7
  • 34
  • 52
  • Thanks, I will take a look at this answer the comment link in detail tomorrow to see which best services my purpose. – dustin Aug 23 '21 at 09:13
  • @dustin I think you should look at mypy (https://mypy.readthedocs.io/en/stable/) as well. It will point to cases like those you mentioned – balderman Aug 23 '21 at 09:28