I just caught myself writing code like this:
def register(self, *, # * enforces keyword-only parameters
key_value_container:dict=None, # legal parameter set #1
key:str=None, value=None): # legal parameter set #2
# enforce one of the parameter sets
if not ((key_value_container is not None and
key is None and value is None) or
(key is not None and value is not None and
key_value_container is None)):
raise TypeError('provide (key_value_container) or (key/value')
# handle each legal parameter setf
if key_value_container is not None:
for _k, _s in key_value_container.items():
self.register(_k, _s)
else:
do_something_with(key, value)
My goal was to have two signatures of the method register()
: it should take a key
and a value
or some container with a number of keys and values e.g. a dict
.
The *
in the argument at least forces me to provide named arguments but there is no need to provide a given number of arguments or even a given set of arguments.
Of course I can (should) provide two methods with different names and signatures instead of one.
But in case I want (have) to provide one method/function with more than one parameter semantics - what's the best way to make this visible and enforce it?
In detail:
- is it possible to make clear in auto-completion and documentation which are the legal parameter combinations?
- how do I check (with as little boilerplate code as possible) whether one combination has been provided?