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 expression The 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 = expression
tells 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
type
statement creates aTypeAliasType
, while: TypeAlias
is basically just like any other variable assignment.That me…