The typing module provides a function get_args which retrieves the arguments with which your Literal was initialized.
>>> from typing import Literal, get_args
>>> l = Literal['add', 'mul']
>>> get_args(l)
('add', 'mul')
However, I don't think you gain anything by using a Literal for what you propose.
Getting the literal out of a python Literal type, at runtime? - Stack Overflow
Inference on Literal Types - Typing - Discussions on Python.org
Python type hints: How to use Literal with strings to conform with mypy? - Stack Overflow
python - Type hinting an object created by typing.Literal[] - Stack Overflow
Videos
The typing module provides a function get_args which retrieves the arguments with which your Literal was initialized.
>>> from typing import Literal, get_args
>>> l = Literal['add', 'mul']
>>> get_args(l)
('add', 'mul')
However, I don't think you gain anything by using a Literal for what you propose.
I'm working with lots of sets of different characters and character sequences and ended up here.
If you're using type aliases defined using the type statement, get_args doesn't work directly.
And a Union of Literals is messy, so the below is what I ended up with:
from collections.abc import Sequence, Iterator
from typing import Literal, get_args, TypeAliasType, cast
def get_literal_vals(alias: TypeAliasType) -> frozenset:
def val(alias: TypeAliasType):
return alias.__value__
def args(alias: TypeAliasType):
return get_args(val(alias))
def resolveT -> Iterator[T]:
if isinstance(alias, TypeAliasType):
for val in resolve(args(alias)):
yield from resolve(val)
return
if isinstance(alias, tuple):
t_seq = cast(Sequence[T], alias)
for element in t_seq:
yield from resolve(element)
return
yield alias
return frozenset(resolve(alias))
type Doubles = Literal["ab", "de", "gh"]
type Triples = Literal["abc", "def", "ghi"]
type DT = Doubles | Triples
dt_set: frozenset[DT] = get_literal_vals(DT)
This has some type checking issues depending on how strict your type checker is but works in practice:
>>> type Triples = Literal["abc", "def", "ghi"]
>>> get_literal_vals(Triples)
frozenset({'def', 'abc', 'ghi'})
>>> type Doubles = Literal["ab", "de", "gh"]
>>> get_literal_vals(Doubles)
frozenset({'gh', 'de', 'ab'})
>>> type DT = Doubles | Triples
>>> get_literal_vals(DT)
frozenset({'ghi', 'de', 'ab', 'abc', 'gh', 'def'})
An interesting side effect of this is that dynamic user input string values can be constrained to a set of specific literal values within conditional branches.
def foo(bar: str):
if bar in dt_set:
# bar is considered a literal value in DT
# by some type checkers.
pass
# bar is an unconstrained string value
# outside of the conditional branch.
My understanding is that Literal objects are the basic dataforms provided by a Programming language, although they all are condensed as binary data string; Literals don't have names, they are literally the data they are representing. Various types of Literals available for programmers to use, is bound by what the programming language is providing. Looking at this in a lower level (CPU and memory level), literals represent the entire binary memory sequence where the corresponding literal's value or data is stored.
Variables, On the other hand, are programming constructs using which one can refer to a literal, by pointing to its memory slice (corresponding starting point in the memory and the size of the literal).
I am unsure, if my above understanding is accurate with the true meaning of the terms Literal and Variable. So, please share your ramifications on my above understanding, and add if I have missed something.