Skip to content Skip to sidebar Skip to footer

Type Hint For An Instance Of A Non Specific Dataclass

I have a function that accepts an instance of any dataclass. what would be an appropriate type hint for it ? haven't found something official in the python documentation this is

Solution 1:

Despite its name, dataclasses.dataclass doesn't expose a class interface. It just allows you to declare a custom class in a convenient way that makes it obvious that it is going to be used as a data container. So, in theory, there is little opportunity to write something that only works on dataclasses, because dataclasses really are just ordinary classes.

In practice, there a couple of reasons why you would want to declare dataclass-only functions anyway, and I see two ways to go about it.


The right way, using a static type checker and writing a Protocol

from dataclasses import dataclassfrom typing importDictfrom typing_extensions import Protocol

classIsDataclass(Protocol):
    # as already noted in comments, checking for this attribute is currently# the most reliable way to ascertain that something is a dataclass
    __dataclass_fields__: Dictdefdataclass_only(x: IsDataclass):
    ...  # do something that only makes sense with a dataclass@dataclassclassA:
    pass

dataclass_only(A())  # a static type check should show that this line is fine

This approach is also what you alluded to in your question, but it has three downsides:

  • You need a third party library such as mypy to do the static type checking for you
  • If you are on python 3.7 or earlier, you need to manually install typing_extensions as well, since Protocol is not part of the core typing module in them
  • Last but not least, using protocols for dataclasses in this way doesn't work right now

Something slightly more EAFP-inspired that actually works

from dataclasses import is_dataclassdef dataclass_only(x):
    """Do something that only makes sense with a dataclass.
    
    Raises:
        ValueError if something that is not a dataclass is passed.
        
    ... more documentation ...
    """ifnot is_dataclass(x):
        raise ValueError(f"'{x.__class__.__name__}' is not a dataclass!")
    ...

In this approach, the behavior is still very clear to a maintainer or user of this code thanks to the documentation. But the downside is that you don't get a static analysis of your code (including type hints by your IDE), not now and not ever.

Solution 2:

There is a helper function called is_dataclass that can be used, its exported from dataclasses.

Basically what it does is this:

defis_dataclass(obj):
    """Returns True if obj is a dataclass or an instance of a
    dataclass."""
    cls = obj ifisinstance(obj, type) elsetype(obj)
    returnhasattr(cls, _FIELDS) 

It gets the type of the instance using type, or if the object extends type, the object itself.

It then checks if the variable _FIELDS, which equals __dataclass_fields__, exists on this object. This is basically equivalent to the other answers here.

To "type" dataclass i would do something like this:

classDataclassProtocol(Protocol):
    __dataclass_fields__: Dict
    __dataclass_params__: Dict
    __post_init__: Optional[Callable]

Post a Comment for "Type Hint For An Instance Of A Non Specific Dataclass"