4

I would like to design a function f(x) whose input could be

  • one object
  • or a list of objects

In the second case, f(x) should return a list of the corresponding results.

I am thinking of designing it as follow.

def f(x):
    if isinstance(x, list):
        return [f(y) for y in x]
    # some calculation
    # from x to result

    return result

Is this a good design? What would be the canonical way to do this?

3
  • It is a common pattern to convert a non-list argument to a one item list at the beginning of the function. Afterwards you don't need to care out the type of the argument anymore. Commented Nov 18, 2016 at 16:59
  • Hi @KlausD. Where can I learn the common design patterns? Is there a book on this? Commented Nov 18, 2016 at 18:28
  • Question for site resources or books are considered off-topic on Stack Overflow. Commented Nov 18, 2016 at 18:30

4 Answers 4

4

No, it's not good design.

Design the function to take only one datatype. If the caller has only one item, it's trivial for them to wrap that in a list before calling.

result = f([list x])

Or, have the function only accept a single value and the caller can easily apply that function to a list:

result = map(f, [x,  y, z])
Sign up to request clarification or add additional context in comments.

1 Comment

I'd say the opposite - design the function to do one thing and let the caller create a list when wanted. But I've done exactly what OP did in a framework where actions on multiple hosts were automatically aggregated by an abstraction layer. I don't think what OP does is definitively poor design in a highly malleable environment like python.
4

They can easily map over the function when they have a list(example):

def f(x):
    return x + 1 #calcuation

lst = map(f, [1, 2, 3])
print(lst) # [2, 3, 4]

And remember: The function should do one thing and do it well :)

Comments

1

I'd avoid it. My biggest issue with it is that sometimes you're returning a list, and sometimes you're returning an object. I'd make it work on a list or an object, and then have the user deal with either wrapping the object, of calling the function in a list comprehension.
If you really do need to have it work on both I think you're better off using:

def func(obj):
    if not isinstance(obj, list):
        obj = [obj]
    # continue

That way you're always returning a list.

Comments

0

Actually the implementation may be valid (but with room for improvement). The problem is that you're creating an ambigous and unexpected behaviour. The best way would be to have 2 different functions f(x) and f_on_list() or something like this, where the second apply the first to a list.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.