我刚刚发现自己编写了这样的代码:
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)
我的目标是拥有方法register()
的两个签名:它应该是key
和value
或某个带有多个键和值的容器,例如dict
。
参数中的*
至少迫使我提供命名参数,但不需要提供给定数量的参数甚至给定的一组参数< / em>的
当然,我可以(应该)提供两种不同名称和签名的方法,而不是一种。
但是如果我希望(有)提供一个具有多个参数语义的方法/函数 - 什么是使其可见并强制执行的最佳方法?
详细说明:
答案 0 :(得分:1)
为了避免样板代码你可以这样:写下指定不同签名的附加函数。然后有一个redirect
辅助函数,它根据参数匹配的签名将主函数的参数发送到附加函数。
它仍然不是特别优雅。如果概括了这一点,您还需要考虑如何处理None
是您可能希望传递的有效参数的情况。
from inspect import getargspec
class Eg(object):
def register(self, key_value_container=None, key=None, value=None):
return redirect(locals(), [self.register_dict, self.register_single])
def register_dict(self, key_value_container=None):
print('register dict', key_value_container)
def register_single(self, key=None, value=None):
print('register single', key, value)
def redirect(params, functions):
provided = {k for k, v in params.items() if v is not None}
for function in functions:
if set(getargspec(function).args) == provided:
return function(**{k: params[k] for k in provided if k != 'self'})
raise TypeError('wrong configuration provided')
# This error could be expanded to explain which signatures are allowed
a = Eg()
a.register(key='hi', value='there')
a.register(key_value_container={'hi': 'there'})