A way to handle single Python shafts and shaft lists the same way?

I often encounter this problem: I create a function that must perform a series of operations on a value, whether it be a single value or a list of values.

Is there an elegant way to do this:

def convert_val(val): do a series of things to each value, whether list or single val return answer or list of answers 

and not what I did ?:

 def convert_val(val): if isinstance(val, list): ... do a series of things to each list item, return a list of answers else: ... do the same series, just on a single value return a single answer 

One solution would be to create sub_convert (), which will perform a series of actions, and then just call it one or more times, depending on the type passed to convert ().

Another would be to create a single convert () that takes arguments (value, sub_convert ()).

Other suggestions that would be more compact, sleek and preferably all in one function?

(I made several requests to check if my problem has already been addressed. My application, if any.)

Thanks JS

+4
source share
3 answers

If a function makes sense both for a single value and for a list, then logically the result of the function for a specific list item will not depend on other items in the list.

For example, a and b must match:

 items = [1, 2] a = convert_val(items) b = map(convert_val, items) 

This example already hints at a solution: the caller knows whether a list or a single value is being transmitted. When transmitting a single value, the function can be used as-is. When you go through the list, the map call is easily added and simplified, which happens on the side of the caller.

Therefore, the function you described should not exist in the first place!

+4
source

You need to fix your design to make all the actions of the function truly correct.

Ralph Waldo Emerson. "Stupid consistency is the hobgoblin of little minds, adored by little statesmen, philosophers and theologians."

We are not talking about a stupid sequence. You have a design issue based on inconsistent use of this feature.

Option 1. Do not call convert_val( x ) , where x is a non-list. Do it. convert_val( [x] ) . Do not correct your function, correct all the places in which your function is used. Consistency helps reduce errors.

Option 2: Modify the convert_val construct to use multiple positional arguments. This is not well generalized.

 def convert_val( *args ): whatever it supposed to do to the arguments. 

Then convert_val( *someList ) all the places where you provided the list convert_val( *someList ) . This is good, and may be closer to your intentions.

Note.

You can find your design errors with the warnings module.

 def convert_val( arg ): if isinstance( arg, collections.Sequence ): return convert_val_list( arg ) else: warnings.warn( "Fix this" ) return convert_val_list( [arg] )[0] def convert_val_list( arg ): assert isinstance( arg, collections.Sequence ) the original processing 

After fixing all design issues, you can do it

 convert_val = convert_val_list 

And remove the original function.

+6
source

I'm late to the party here and I'm not sure if this is what the OP wants.

I prefer to keep implementation details hidden inside the function. The caller does not have to care about what is happening inside.

 def convert_val(val): values = [] values.extend(val) for value in values: # do things to each list item, return a list of answers 

This would make convert_val put val in the values list (if not a list) or all val values ​​in the values list.

In addition, you should predict getting the list back (since you will use the same logic).

In the end:

 assert convert_val([1]) == convert_val(1) 
0
source

Source: https://habr.com/ru/post/1315966/


All Articles