2

I'm not an experienced Python programmer but I feel my solution to this problem isn't right, I think there is a better way to deal with this problem in Python.

In this case, this is using Hug API but that's probably mostly irrelevant.

Let's say the code is like this:

@hug.get_post('/hello')
def hello (name)
   print(type(name))
   return name

When a request is sent with one instance of the name parameter, the hello function gets a str - as in:

POST /hello?name=Bob

But if the request is sent multiple name parameters, the method receives a list of strings, as in

POST /hello?name=Bob&name=Sally

If I write the method like the following:

@hug.get_post('/hello')
def hello (name: list)
   print(type(name))
   return name

Then the single parameter becomes a list of characters. I.e. ['B', 'o', 'b']. But this works fine if there is multiple instances of the name parameter (e.g. ['Bob', 'Sally'] )

So the way I solved it right now is by adding this code:

@hug.get_post('/hello')
def hello (name)
   names=list()
   if type(name) != 'list'
      names.append(name)
   else:
      names=name
   return names

This works, but feels wrong. I think there is a better way to do this but I can't figure it out at the moment.

ETL
  • 9,281
  • 3
  • 29
  • 28
  • This is definitely incorrect: `if type(name) != 'list'` the result of `type` will never equal a string. `type` returns a class object, so here you would use `if type(name) is not list` but you should use `isinstance` for something more idiomatic – juanpa.arrivillaga Nov 05 '19 at 02:21

3 Answers3

1

If you want to be more concise you could use the ternary operator like so:

@hug.get_post('/hello')
def hello (name)
   return name if isinstance(name, list) else [name]
umarkhan
  • 26
  • 2
1

Hug provides a type for that: hug.types.multiple

import hug
from hug.types import multiple

@hug.get()
def hello(name: multiple):
    print(type(name))

    return name

Now /hello?name=Bob returns ['Bob'] and /hello?name=Bob&name=Sally returns ['Bob', 'Sally'].

If you want to validate the inner elements, you can create a customized type like this:

import hug
from hug.types import Multiple, number

numbers = Multiple[number]()

@hug.get()
def hello(n: numbers):
    print(type(n))

    return n

In this case /hello?n=1&n=2 returns [1, 2] and /hello?n=1&n=a results in an error:

{"errors": {"n": "Invalid whole number provided"}}

Wombatz
  • 4,958
  • 1
  • 26
  • 35
0

I'm not sure you can do it in a much more elegant matter.

isinstance() is a very common way of checking types. Below code can handle tuples, lists or strings

@hug.get_post('/hello')
def hello (name):
   if isinstance(name, (list, tuple)):
      names = name
   else:
      names = [name]      
   return names
gelonida
  • 5,327
  • 2
  • 23
  • 41