Способ одинаково обрабатывать одиночные валы Python и списки валов?

Я часто сталкиваюсь с этой проблемой: я создаю функцию, которая должна выполнять серию операций над значением, будь то одно значение или список значений.

Есть ли элегантный способ сделать это:

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

а не то, что я делал ?:

 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 

Одним из решений было бы создать sub_convert (), который будет выполнять серию действий, а затем просто называть его один или несколько раз, в зависимости от типа, переданного в convert ().

Другим было бы создание единственного convert (), которое принимало бы аргументы (value, sub_convert ()).

Другие предложения, которые были бы более компактными, изящными и предпочтительно все в одной функции?

(Я сделал несколько поисков здесь, чтобы узнать, была ли моя проблема уже рассмотрена. Мое приложение, если оно есть.)

Спасибо, JS

Если функция имеет смысл как для одного значения, так и для списка, то логически результат функции для определенного элемента списка не будет зависеть от других элементов в списке.

Например, a и b должны совпадать:

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

Этот пример уже намекает на решение: вызывающий абонент знает, передается ли список или одно значение. При передаче одного значения функция может использоваться как-есть. При прохождении списка можно легко добавить вызов map и сделать более понятным, что происходит на стороне вызывающего.

Следовательно, функция, которую вы описываете, не должна существовать в первую очередь!

Вам нужно исправить свой дизайн, чтобы все функции функции действительно были правильными.

Ральф Уолдо Эмерсон. «Глупая последовательность – это хобгоблин маленьких умов, обожаемый маленькими государственными деятелями, философами и богословами».

Мы не говорим о глупой последовательности. У вас есть проблема с дизайном, основанная на непоследовательном использовании этой функции.

Вариант 1. Не вызывайте convert_val( x ) где x является списком. Сделай это. convert_val( [x] ) . Не исправляйте свою функцию, исправьте все места, в которых используется ваша функция. Консистенция помогает уменьшить количество ошибок.

Вариант 2. Измените дизайн convert_val для использования нескольких позиционных аргументов. Это не очень хорошо обобщается.

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

Затем закрепите все места, где вы предоставляете список, который будет convert_val( *someList ) . Это нормально и может быть ближе к вашим намерениям.

Заметка.

Вы можете найти свои ошибки в дизайне с помощью модуля warnings .

 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 

После устранения всех проблем с дизайном вы можете сделать это

 convert_val = convert_val_list 

И удалите исходную функцию.

Я опаздываю на вечеринку здесь, и я не уверен, что это то, чего хочет OP.

Я предпочитаю держать детали реализации скрытыми внутри функции. Вызывающий не должен заботиться о том, что происходит внутри.

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

Это сделало бы convert_val put val в список values (если не список) или все значения val в списке values .

Кроме того, следует предсказуемо получить список обратно (поскольку вы будете использовать ту же логику).

В конце:

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