I have a function whose input argument can either be an element or a list of elements. If this argument is a single element then I put it in a list so I can iterate over the input in a consistent manner.
Currently I have this:
def my_func(input):
if not isinstance(input, list): input = [input]
for e in input:
...
I am working with an existing API so I can't change the input parameters. Using isinstance() feels hacky, so is there a proper way to do this?
Convert a frozenset to a list. The Python frozenset object is similar to a set but is immutable. Therefore, we cannot modify the elements of a frozenset. We can convert this type of set too, using list().
Typecasting to list can be done by simply using list(set_name) . Using sorted() function will convert the set into list in a defined order.
Python String is a sequence of characters. We can convert it to the list of characters using list() built-in function. When converting a string to list of characters, whitespaces are also treated as characters. Also, if there are leading and trailing whitespaces, they are part of the list elements too.
Typically, strings (plain and unicode) are the only iterables that you want to nevertheless consider as "single elements" -- the basestring
builtin exists SPECIFICALLY to let you test for either kind of strings with isinstance
, so it's very UN-grotty for that special case;-).
So my suggested approach for the most general case is:
if isinstance(input, basestring): input = [input]
else:
try: iter(input)
except TypeError: input = [input]
else: input = list(input)
This is THE way to treat EVERY iterable EXCEPT strings as a list directly, strings and numbers and other non-iterables as scalars (to be normalized into single-item lists).
I'm explicitly making a list out of every kind of iterable so you KNOW you can further on perform EVERY kind of list trick - sorting, iterating more than once, adding or removing items to facilitate iteration, etc, all without altering the ACTUAL input list (if list indeed it was;-). If all you need is a single plain for
loop then that last step is unnecessary (and indeed unhelpful if e.g. input is a huge open file) and I'd suggest an auxiliary generator instead:
def justLoopOn(input):
if isinstance(input, basestring):
yield input
else:
try:
for item in input:
yield item
except TypeError:
yield input
now in every single one of your functions needing such argument normalization, you just use:
for item in justLoopOn(input):
You can use an auxiliary normalizing-function even in the other case (where you need a real list for further nefarious purposes); actually, in such (rarer) cases, you can just do:
thelistforme = list(justLoopOn(input))
so that the (inevitably) somewhat-hairy normalization logic is just in ONE place, just as it should be!-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With