Python – How to Handle Singular and Plural Parameters for Functions

parameterspython

Often when I'm writing a set of utility functions, I find myself wanting a function that applies some logic to multiple items, as well as a function that does the same with just a single item. There are a lot of potential solutions to this, but I always find myself flipping back and forth.

  • I could write an exclusively singular version of the function (modify_item(item)) and use map, comprehension, or a foreach externally. I don't want to do this every danged time I call it with multiple items though.
  • I could write an exclusively explicitly plural version of the function (modify_items(items)) that does the iteration inside. But I don't want to call it with a list every time either. Better than always singular, but still awkward to call. This would also support bulk operations better.
  • I could write an agnostic function that checks the input's type (modify_item(item)). If it's not iterable, it'll wrap it in a list and then iterate. This seems to be the best option, but the lure of star operators always gets me…
  • I could write an agnostic function that takes a variable number of inputs (modify_item(*items)) and iterates over them. This gives me a good calling syntax and automatically packs the items into an iterable for me. The problem I always run into here is that adding subsequent arguments or keyword arguments is awkward.
  • Finally, I could just throw up my hands and write a plural function as above, and a singular one that would wrap the parameter in a list and pass it to the plural one. Then I'd have to write double the functions, which is silly.

It seems like javascript libraries usually do the type checking option (#3), and that's the one I like best. In that case, you have the question of naming conventions. I think I favor singular, but I'm not sure about that.

Examples are in python, but this question could be applied to most languages.

Best Answer

In these instances, I usually make two versions of the function, with the multiple version simply calling the singular version, something like this:

class Foo:
  def transform_entity(bar):
    return do_things(bar)

  def transform_entities(bars):
    return [transform_entity(b) for b in bars]

It's pretty self-explanatory, avoids any explicit wrapping, and allows you to use arguments properly without manual wrapping (unlike trying to do something terrible with varargs).

Related Topic