【问题标题】:Set function parameters based on the value of another parameter根据另一个参数的值设置函数参数
【发布时间】: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


【解决方案1】:

您可以使用返回所需函数类型的函数。像这样:

import random
def generate(dist):
    if dist == 'uniform':
        def uniformDist(lower=0, upper=1):
            return random.uniform(lower,upper)
        return uniformDist

    if dist == 'poisson':
        def poissonDist(lmbda=1,):
            return poisson(lmbda)
        return poissonDist

print(generate('poisson')(lmbda=3))
print(generate('uniform')(lower=34, upper=78))

【讨论】:

  • 感谢您的回答,这可能是我想要的。您能否详细说明或指出一些讨论这种方法的优缺点的内容?
  • @LoganYang 这是根据您的要求直接实现的。这样做的缺点是,除非您有一个非常智能的 IDE,否则在填充返回函数的参数时将没有自动完成帮助。此外,使用背靠背的双括号有点令人困惑。优点是,当您提供错误的关键字参数时,它会提前失败并让您知道原因。
猜你喜欢
  • 1970-01-01
  • 2014-09-02
  • 2021-01-31
  • 1970-01-01
  • 2017-02-03
  • 2011-05-04
  • 2023-03-11
  • 2016-05-10
  • 2015-11-05
相关资源
最近更新 更多