【发布时间】:2018-11-30 20:47:49
【问题描述】:
如果标题含糊不清,我深表歉意。让我解释一下情况。
假设我想根据某个分布生成一些随机数,它可以是均匀的、正态的、泊松的、二项式的等。每个分布都有自己的参数/关键字参数来定义,例如normal 有 mean 和 std,Poisson 有 lambda,uniform 有 upper_bound 和 lower_bound,依此类推。如何定义这个函数的签名,它应该将分布类型作为一个字符串作为一个参数,并且根据它的值,该函数应该具有必需的(关键字)参数,也就是分布参数,如均值和标准?
def generate(distribution, params):
"""
Args:
distribution (str): can take values 'uniform', 'normal', 'poisson', etc.
params (dict of str: float): based on the value of distribution, it should have the required parameters for the distribution
"""
if distribution == 'uniform':
result = uniform(params['lower'], params['upper'])
elif distribution == 'normal':
result = normal(params['mean'], params['std'])
elif distribution == 'poisson':
result = poisson(params['lambda'])
elif ...:
...
我能想到的一个选项就是在签名中添加 **kwargs,我可以在其中直接插入关键字参数 mean、std、lambda 等。但这很混乱,并且没有反映给定分布的相关所需参数。我想知道 Pythonic 的方法是什么。
这只是一个例子,我的问题是,当某些参数依赖于与函数相关的其他参数的值时,我应该如何编写函数签名。这可能不仅仅是关于 Python,它更像是一个与编程/语言无关的一般问题。
我觉得现在应该有一个简单明了的解决方案。任何建议表示赞赏。
【问题讨论】:
-
当您发现自己不得不传递触发动态行为的字符串时:可能是时候创建具有自己内部定义行为的类型化类了。您可以从一个名为
Distribution的抽象超类开始,然后为您的每个变体子类化它。 -
如果你想要不同的签名,把它分成不同的功能。不要过于复杂。例如:
def generate_uniform(lower, upper):... -
@SuperShoot 感谢 cmets。所以基本上我不能在所有这些不同的随机数生成器上都有一个包装函数?
-
是的,您可以,就像您已经使用
**kwargs一样。但是如果你想要不同的函数签名,你将需要不同的函数。将第三方函数包装在您自己的函数中是有好处的:它将第三方函数转化为实现细节,并且可以轻松地在测试中模拟返回。 -
@LoganYang 如果你的包装函数只是委托给具有完美签名的现有函数,它会增加什么价值?如果要为所需参数提供默认值,否则将没有任何参数,您可能需要查看
functools.partial以包装这些 individual 函数。
标签: python function parameter-passing