Michael Eltham
Michael Eltham

Reputation: 107

Need to shrink my large if elif statement in python

I trying to see if there is a more efficient way to write if elif statement. Writing an API to generate a url based on the number of parameters the class is called.

For Ex:

def Cars(self, model=null, color=null, miles=null)

    if model == null and color == null and miles ==null:
        url = cars/
    elif model != null and color == null and miles ==null:
        url = cars/model=%s)% model
    elif model != null and color != null and miles ==null:
        url = cars/model=%s/color=%s)% model, color
    else url = someting

    return url

I have more than 10 parameters and don't want to write that many elif statements with all the combinations..

Upvotes: 0

Views: 1036

Answers (5)

Deacon
Deacon

Reputation: 3803

Like chepner's answer (and others in the comments), my thought was to use keyword arguments. However, rather than using url += ... each time through the loop, my approach is generally to append the parameters to a list, and then use .join() to create the final string once the parameter list has been created. That way I don't have to worry about whether I'm formatting the string correctly; I can let Python take care of that headache.

I only post this to demonstrate an alternate method using the same starting point.

def cars(**kwargs):  # If using as part of a class, would be cars(self, **kwargs)
    params = []
    for key in kwargs.keys():
        # Append `key=value` to `params`.
        if kwargs.get(key):
            params.append('{!s}={!s}'.format(key, kwargs[key]))
    url = '/cars?{!s}'.format('&'.join(params))
    return url

print(cars(make='Ford', model='Taurus', year=2000, colors='white'))

Upvotes: 0

Sniggerfardimungus
Sniggerfardimungus

Reputation: 11831

If you are simply patterning your url, where each parameter gives a substring to the url, you can do something like this:

url = 'http://foo.com/'
if model is not None:
    url += 'model={}'.format(model)
if color is not None:
    url += 'color={}'.format(model)
if miles is not None:
    url += 'miles={0:.1f}'.format(model)

If you don't need any custom formatting per parameter, you can collapse all of that to this:

url = 'http://foo.com/'
for parameter in ['model', 'color', 'miles']:
    url += '{}={}'.format(parameter, locals()[parameter])

Upvotes: 0

jure
jure

Reputation: 412

Ignoring all your mistakes in the code... what about:

url = "cars"
if model:
    url += "/model={}".format(model)
if color:
    url += "/color={}".format(color)
if ...

Upvotes: 0

Marcus
Marcus

Reputation: 1713

You could perhaps do something like this:

def Cars(self, model=null, color=null, miles=null)

    url = "cars/"
    if ( model ) :
        url += "/models=%s" % model

    if ( color ) :
        url += "/color=%s" % color

    if ( miles ) :
        url += "/miles=%s" % miles

    return url

In writing it this way, you'll avoid having to use combinatorics. In your code, you'll have 9 if..else statements, here we have only three.

Upvotes: 0

chepner
chepner

Reputation: 531420

The attributes don't appear to be dependent on each other; handle each one separately:

def cars(self, model=None, color=None, miles=None)
    url = "cars"

    if model is not None:
        url += "/model=%s" % (model,)
    if color is not None:
        url += "/color=%s" % (color,)
    if miles is not None:
        url += "/miles=%s" % (miles,)

    return url

This leads to the realization that you probably want to accept arbitrary keyword arguments, and check for the existence of a specific set:

def cars(self, **kwargs):
    url = "cars"
    for kw in ["model", "color", "miles"]:
        if kwargs.get(kw) is not None:
            url += "/%s=%s" % (kw, kwargs[kw])
    return url

This ignores the issue of whether or not the string you are building is, in fact, a valid URL.

Upvotes: 9

Related Questions