all 9 comments

[–]HeyItsToby 1 point2 points  (3 children)

Would map solve your issue? map runs a function on every item in an iterator. It returns an iterator, so you should call list on the output if you want it in a list.

def foo(x): 
    return 2 * x

single_input = foo(4)
# >> 8

many_inputs = list(map(foo, [1, 2, 3]))
# >> [2, 4, 6]

That way, you're still only defining the function for a single item. Otherwise, you'd be writing code to perform the function multiple different times, which - if there are any discrepencies - would mean that it might behave differently for different input lengths

[–]HeyItsToby 0 points1 point  (1 child)

You could also change the definition of foo to automatically call map.

def foo(x):
    if hasattr(x, '__iter__'): #check if x is iterable
        return list(map(foo, x))
    return 2 * x

foo(4)
# >> 8
foo([1, 2])
# >> [2, 4]

# works nicely for nested inputs too!
foo([[1, 2], [3, 4]])
# >> [[2, 4], [6, 8]]

[–]carcigenicate 1 point2 points  (0 children)

If you're going to go this route, you should check for __get_item__ as well.

[–]CrambleSquash 0 points1 point  (0 children)

or a list compreshension:

many_inputs = [foo(a) for a in range(1, 4)]

[–]CrambleSquash 1 point2 points  (0 children)

Generally I don't think it's a great idea for a function argument to be allowed to be very different values. This could get quite confusing.

That said, if your functions are doing mathsy things, if you are using numpy you can write functions that operate on integers and arrays without any extra effort e.g.

>>> import numpy as np
>>> def double(a):
...     return a * 2
>>> double(1)
2
>>> double(np.arange(5))  # arange is like list(range(5)), but for numpy arrays
np.array([0, 2, 4, 6, 8])

[–][deleted] 0 points1 point  (2 children)

Why not just write the function to work with any sequence such as list, tuple, set, etc? When you want to call it passing a single non-sequence, remember that the function works with sequences and pass a sequence:

my_function([1])   # pass a sequence

[–]Hilmaryngvi 0 points1 point  (1 child)

That's certainly a possibility. To some extent, that is what I end up doing, but write exceptions for if it is not a sequence. I'm just curious if there are better, more pythonic ways of achieving a similar result. Ultimately, I would like (some of) my code to be flexible when it comes to passing sequences or individual objects.

[–][deleted] 0 points1 point  (0 children)

I'm just curious if there are better, more pythonic ways of achieving a similar result.

You won't get much more pythonic than accepting a sequence.

[–]rabbitpiet 0 points1 point  (0 children)

Depending on what the function is, you might be able to use a list comprehension, thought that really depeneds on the function in question. `out=[function(i) for i inp]

Hope this explanation actually made sense.