When using TypeAlias, does the interpreter always substitute the type for the TypeAlias? #2092
-
| This is what I see when I use a TypeAlias. from typing import TypeAlias type alphaKeyword = float betaAssignment: TypeAlias = float chicken: alphaKeyword = 8.9 silky = betaAssignment(21.56) print(type(chicken)) print(type(silky)) <class 'float'> <class 'float'>I'm all but certain that is working exactly as intended. But I want to make sure I didn't miss something. When I use a TypeAlias, I would like to be able to programmatically get the TypeAlias later. One way I work around it.
from https://github.com/hunterhogan/mapFolding from mapFolding import ( Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal, getConnectionGraph, getLeavesTotal, makeDataContainer) import dataclasses @dataclasses.dataclass(slots=True) class MapFoldingState: mapShape: tuple[DatatypeLeavesTotal, ...] = dataclasses.field(init=True, metadata={'elementConstructor': 'DatatypeLeavesTotal'}) groupsOfFolds: DatatypeFoldsTotal = dataclasses.field(default=DatatypeFoldsTotal(0), metadata={'theCountingIdentifier': True}) gap1ndex: DatatypeElephino = DatatypeElephino(0) gap1ndexCeiling: DatatypeElephino = DatatypeElephino(0) indexDimension: DatatypeLeavesTotal = DatatypeLeavesTotal(0) indexLeaf: DatatypeLeavesTotal = DatatypeLeavesTotal(0) indexMiniGap: DatatypeElephino = DatatypeElephino(0) leaf1ndex: DatatypeLeavesTotal = DatatypeLeavesTotal(1) leafConnectee: DatatypeLeavesTotal = DatatypeLeavesTotal(0) dimensionsUnconstrained: DatatypeLeavesTotal = dataclasses.field(default=None, init=True) countDimensionsGapped: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) gapRangeStart: Array1DElephino = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DElephino.__args__[1].__args__[0]}) gapsWhere: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) leafAbove: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) leafBelow: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) connectionGraph: Array3DLeavesTotal = dataclasses.field(init=False, metadata={'dtype': Array3DLeavesTotal.__args__[1].__args__[0]}) dimensionsTotal: DatatypeLeavesTotal = dataclasses.field(init=False) leavesTotal: DatatypeLeavesTotal = dataclasses.field(init=False) @property def foldsTotal(self) -> DatatypeFoldsTotal: return DatatypeFoldsTotal(self.leavesTotal) * self.groupsOfFolds def __post_init__(self) -> None: self.dimensionsTotal = DatatypeLeavesTotal(len(self.mapShape)) self.leavesTotal = DatatypeLeavesTotal(getLeavesTotal(self.mapShape)) leavesTotalAsInt = int(self.leavesTotal) self.connectionGraph = getConnectionGraph(self.mapShape, leavesTotalAsInt, self.__dataclass_fields__['connectionGraph'].metadata['dtype']) if self.dimensionsUnconstrained is None: self.dimensionsUnconstrained = DatatypeLeavesTotal(int(self.dimensionsTotal)) if self.gapsWhere is None: self.gapsWhere = makeDataContainer(leavesTotalAsInt * leavesTotalAsInt + 1, self.__dataclass_fields__['gapsWhere'].metadata['dtype']) if self.countDimensionsGapped is None: self.countDimensionsGapped = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['countDimensionsGapped'].metadata['dtype']) if self.gapRangeStart is None: self.gapRangeStart = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['gapRangeStart'].metadata['dtype']) if self.leafAbove is None: self.leafAbove = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafAbove'].metadata['dtype']) if self.leafBelow is None: self.leafBelow = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafBelow'].metadata['dtype']) |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
| It's not entirely clear to me what exactly you want to achieve. I give you the broad rundown The usage of Foo = "int | str" # interpreted as string Bar: TypeAlias = "int | str" # interpreted as a Union type expressionThe most crucial runtime difference is that the print(Bar is "int | str") # true type Baz = "int | str" print(Baz is "int | str") # false; but equivalent That means in your case From your dataclass example I am not entirely sure what you want to achieve, or what to focus on. Save the dtype as metadata? Or do you want to avoid this and get Generally a good was is to use Here you see with Note that this behavior changes when # get_type_hints evaluated: {'a': alphaKeyword, 'b': <class 'float'>, 'c': <class 'float'>, 'd': <class 'float'>} {'c': <class 'float'>, 'd': <class 'float'>} # get_annotations as strings {'a': 'alphaKeyword', 'b': 'betaAssignment'} {'c': 'float', 'd': "'float'"}Similarly you can also apply it to modules: # foo.py a: int b: float type C = "int | str" D = "int | str" c: "C" d: D # no annotation for cases below: I = int i = I(2) from typing import NewType I2 = NewType("I2", int) i2 = I2(3)import foo from typing_extensions import get_type_hints, get_annotations get_type_hints(foo) # {'a': int, 'b': float, 'c': C, 'd': int | str} get_annotations(foo) {'a': int, 'b': float, 'c': 'C', 'd': 'int | str'}I hope that gave you some insights and the tools you need to achieve what you need. |
Beta Was this translation helpful? Give feedback.
It's not entirely clear to me what exactly you want to achieve. I give you the broad rundown
The usage of
var: TypeAlias = expressiontells your type-checker to interpret the assignment as a type expression. One of the most important cases is to distinguish strings vs type expressions written as strings.The most crucial runtime difference is that the
typestatement creates aTypeAliasType, while: TypeAliasis basically just like any other variable assignment.That me…