Let’s say I have a class:
JavaScript
x
19
19
1
from typing import Literal
2
3
4
class Computer:
5
def __init__(self, operation: Literal['floor', 'ceil', 'square']):
6
if operation not in ('floor', 'ceil', 'square'):
7
raise ValueError(f'Invalid operation "{operation}"')
8
self._operation = operation
9
10
# ... lots of methods that use `self._operation`, e.g.
11
def is_much_larger(self, value: float) -> bool:
12
if self._operation == 'square':
13
if value > 1:
14
return True
15
else:
16
return False
17
else:
18
return False
19
I would like to maintain the list of viable values, i.e. 'floor', 'ceil', 'square'
, in only one place. What’s a good recipe for this?
The MyPy docs show some ideas with this suggestion of assert_never
but that’s just for MyPy to give an error before runtime, not as a way to maintain a single list of values.
Advertisement
Answer
You can introspect those arguments using the typing module.
JavaScript
1
5
1
>>> import typing
2
>>> Operation = typing.Literal['floor', 'ceil', 'square']
3
>>> typing.get_args(Operation)
4
('floor', 'ceil', 'square')
5
You could use a type alias then get the values you want using typing.get_args
, so something like:
JavaScript
1
23
23
1
import typing
2
3
# in Python >= 3.10 , use explicit type alias:
4
# Operation: typing.TypeAlias = typing.Literal['floor', 'ceil', 'square'
5
Operation = typing.Literal['floor', 'ceil', 'square']
6
7
8
class Computer:
9
def __init__(self, operation: Operation:
10
if operation not in typing.get_args(Operation):
11
raise ValueError(f'Invalid operation "{operation}"')
12
self._operation = operation
13
14
# ... lots of methods that use `self._operation`, e.g.
15
def is_much_larger(self, value: float) -> bool:
16
if self._operation == 'square':
17
if value > 1:
18
return True
19
else:
20
return False
21
else:
22
return False
23