J
Jan Kaliszewski
[...]Thanks for all the answers. Let me summarize
(1) [...]
(2) Using enum's was suggested. That is good to know, but again it is
just a way to define constants in the caller's namespace. [...]
(3) Then somone suggested to tie the constants to the function itself,
[...]
(4) Finally someone mentioned DSLs. [...]
(5) Here is something I came up with myself:
def symbols(aDict):
aDict["foo"] = "bar"
def someFunction(aFoo):
print aFoo
symbols(locals())
someFunction (foo) #Eh voila: foo is magically defined
And what about such a sollution (6):
from functools import wraps
def restrict(*arg_options):
"Decorator that restricts positional arg values to a limited set."
options = set(arg_options)
def actual_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
if options.issuperset(args):
func(*args, **kwargs)
else:
raise ValueError("possible positional arguments"
" for %s() limited to: %s"
% (func.__name__,
", ".join(map(repr,
arg_options))))
return wrapper
return actual_decorator
@restrict('up', 'down', 'right', 'left')
def move(direction):
print(direction)
# ...
move('up') # OK
move('down') # OK
move('left') # OK
move('right') # OK
move('rihgtt') # raises ValueError
Although it uses strings, it solves (in Pythonic, explicit way) the main
problem: "you could pass invalid strings easily". Typing a two characters
more ('') isn't a big effort.
Please also note that you can apply not only str-based symbols but any
hashable objects (obviously it could be event implemented in less
efficient way to accept *any* objects, though I doubt it's worth to do...).
Regards,
*j