Logan Yang
Logan Yang

Reputation: 2594

Set function parameters based on the value of another parameter

I apologize if the title is vague. Let me explain the situation.

Say I want to generate some random number based on some distribution, it can be uniform, normal, Poisson, Binomial, etc. Each distribution has its own parameters / keyword arguments to define, e.g. normal has mean and std, Poisson has lambda, uniform has upper_bound and lower_bound, and so on. How do I define the signature of this function which should take in the type of distribution as a string as one argument, and depending on the value of it, the function should have required (keyword) arguments aka distribution parameters like mean and std?

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 ...:
        ...

One option I can think of is just to have **kwargs in the signature where I can plug in keyword arguments mean, std, lambda and so on directly. But that is quite messy and it doesn't reflect the relevant required arguments given a distribution. I wonder what is the Pythonic way to do this.

This is just an example, my question is that in general how should I write the function signature when some arguments depend on the value of other arguments to be relevant for the function. And this might not just be about Python, it's more of a general programming / language agnostic question.

I feel there should be a straightforward and clean solution which eludes me now. Any suggestion is appreciated.

Upvotes: 0

Views: 1056

Answers (1)

rajendra
rajendra

Reputation: 502

You can use a function that returns the required type of function. Like this:

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))

Upvotes: 1

Related Questions