I have a Python class with special values, "EMPTY" and "UNIVERSE":
class RealSet:
"""Continuous open, half-open, and closed regions and discreet values of the Reals"""
# implementation placeholder
def __init__(self, intervals, *, canonicalize):
pass
# Outside the class
RealSet.EMPTY = RealSet(tuple(), canonicalize=False) # type: ignore
RealSet.UNIVERSE = RealSet(((None, None),), canonicalize=False) # type: ignore
However, linting, code-completion, etc. don't like this because they're not seen as static attributes of the class. Even setting them is reported as a mypy error, hence the # type: ignore
.
The below doesn't work because I can't construct a RealSet
in the class scope because it doesn't exist yet:
class RealSet:
"""Continuous open, half-open, and closed regions and discreet values of the Reals"""
...
...
EMPTY = RealSet(tuple(), canonicalize=False) # error
UNIVERSE = RealSet(((None, None),), canonicalize=False) # error
And this doesn't work because it defines instance attributes, not class attributes:
class RealSet:
"""Continuous open, half-open, and closed regions and discreet values of the Reals"""
...
...
EMPTY: "RealSet"
UNIVERSE: "RealSet"
# Outside the class
RealSet.EMPTY = RealSet(tuple(), canonicalize=False)
RealSet.UNIVERSE = RealSet(((None, None),), canonicalize=False)
This seems to be a corner case in the design of Python classes. How can I make class attributes where the attribute's type is the class in which it resides? Bonus: make them constant.
You can use typing.ClassVar
to annotate class variables:
class RealSet:
def __init__(self, intervals, *, canonicalize):
pass
EMPTY: ClassVar['RealSet']
UNIVERSE: ClassVar['RealSet']
RealSet.EMPTY = RealSet(tuple(), canonicalize=False)
RealSet.UNIVERSE = RealSet(((None, None),), canonicalize=False)