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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.