强制特定函数签名
Force specific function signatures
我刚发现自己在写这样的代码:
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
.
参数中的 *
至少迫使我提供命名参数,但没有必要提供 给定数量的参数 甚至 一组给定的参数.
当然我可以(应该)提供两种不同名称和签名的方法,而不是一种。
但万一我想(必须)提供一个 method/function 具有多个参数语义 - 使它可见并强制执行它的最佳方法是什么?
详细:
- 能否在自动补全和文档中明确哪些是合法的参数组合?
- 如何检查(使用尽可能少的样板代码)是否提供了一种组合?
为了避免样板代码,您可以这样做:编写额外的函数来指定不同的签名。然后有一个 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'})
我刚发现自己在写这样的代码:
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
.
参数中的 *
至少迫使我提供命名参数,但没有必要提供 给定数量的参数 甚至 一组给定的参数.
当然我可以(应该)提供两种不同名称和签名的方法,而不是一种。
但万一我想(必须)提供一个 method/function 具有多个参数语义 - 使它可见并强制执行它的最佳方法是什么?
详细:
- 能否在自动补全和文档中明确哪些是合法的参数组合?
- 如何检查(使用尽可能少的样板代码)是否提供了一种组合?
为了避免样板代码,您可以这样做:编写额外的函数来指定不同的签名。然后有一个 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'})