2

I have the following code for making a RESTful call to a server:

def request(self, request, account_id, user):

    if request is 'get_id':
        #Get user from id
        result = requests.get(api_root + "/accounts/" + account_id + "/users/" + user, headers=self.headers)

    elif request is 'get_username':
        #Get user from username
        result = requests.get(api_root + "/accounts/" + account_id + "/users?username=" + user, headers=self.headers)

    elif request is 'get_email':
        #Get user from username
        result = requests.get(api_root + "/accounts/" + account_id + "/users?email=" + user, headers=self.headers)

    elif request is 'post':
        #Add user to new account
        result = requests.post(api_root + '/accounts/' + account_id + '/users', data=json.dumps(user), headers=self.headers)

    elif request is 'delete':
        #Delete user from account
        result = requests.delete(api_root + "/accounts/" + account_id + "/users/" + user, headers=self.headers)

    #Throw exception if non-200 response
    result.raise_for_status()

    #Print request result / status
    print "\nRequest " + request + " Result: " + result.text + "\nStatus: " + str(result.status_code)

    return result

I know this is ugly and I wanted to change it into a dictionary, something like:

def request(self, request, account_id, user):
    url = api_root + "/accounts/" + account_id

    function_dictionary = {}
    function_dictionary['get_id']       = requests.get(url + "/users/" + user, headers=self.headers)
    function_dictionary['get_username'] = requests.get(api_root + "/accounts/" + account_id + "/users?username=" + user, headers=self.headers)
    function_dictionary['get_email']    = requests.get(api_root + "/accounts/" + account_id + "/users?email=" + user, headers=self.headers)
    function_dictionary['delete']       = requests.delete(url + "/users/" + user, headers=self.headers)
    function_dictionary['post']         = requests.post(url + '/users', data=json.dumps(user), headers=self.headers)  

    result = function_dictionary.get(request)

    #Throw exception if non-200 response
    result.raise_for_status()
    return result

I still have a feeling I am going about it the wrong way. Can anybody tell me what the proper method to approach if / elseif statements in Python is?

Thanks!

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
TomSelleck
  • 6,706
  • 22
  • 82
  • 151

1 Answers1

8

Using a dict to replace if: elif: loops is certainly Pythonic, but note that in your example you are calling requests.get etc for every case you store in the dictionary, i.e. the dictionary values are the results of those calls.

An alternative would be to store function and arguments separately in the dictionary:

function_dict = {'get_id': (requests.get, # function
                            (url + "/users/" + user,), # tuple of arguments  
                            {'headers': self.headers}), # dict of keyword args
                 ...}

Now you can use

func, args, kwargs = function_dict[request]
result = func(*args, **kwargs)

Also, note that comparing strings using is is a bad idea (although it sometimes works); it is better to use ==:

if request == 'get_id':
Community
  • 1
  • 1
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • 2
    check tuple here: headers=self.headers... invalid syntax – ndpu Jan 10 '14 at 14:45
  • Wow this is very cool, just a couple of things, `function_dict(request)` should be `function_dict[request]` right? And for my `post` request, how should I include `data=json.dumps(user)`? I am getting a syntax error, will update my question. – TomSelleck Jan 10 '14 at 15:44
  • Rather than storing functions and arguments separately, just use a `lambda`. That's what they're for! – kindall Jan 10 '14 at 15:49
  • 1
    @Tomcelic yes, should have been `[]`; fixed. `json.dumps` is for a keyword argument, `data`, so should be in the dictionary with `headers`. – jonrsharpe Jan 10 '14 at 15:55