Как создать listcomp для перечисления значений, отличных от списка, а затем сгладить все с помощью itertools?

#python #python-3.x

#python #python-3.x

Вопрос:

Я спрашиваю вас здесь о проблеме в названии, потому что я новичок в Python и особенно в создании listcomps.

Я хотел бы создать простую функцию для:

  1. проверьте, являются ли все аргументы *args списками
  2. если нет, то значение преобразуется в список
  3. сгладить все с помощью itertools

Ниже вы можете найти мой код:

 import itertools


def lstfunc(*args):
    lstargs = list(args)
    for i in lstargs:
        if not isinstance(i, list):
            lstargs[lstargs.index(i)] = [i]
    lstargs = list(itertools.chain.from_iterable(lstargs))
    return lstargs


print(lstfunc([1, 2, 3], 4, 5))
  

Вывод: [1, 2, 3, 4, 5] (правильно).

Мой вопрос в том, как создать listcomp из этой части:

     for i in lstargs:
        if not isinstance(i, list):
            lstargs[lstargs.index(i)] = [i]
  

Я пытался:

 import itertools


def lstfunc(*args):
    lstargs = list(args)
    lstargs = [[i] for i in lstargs if not isinstance(i, list)]
    lstargs = list(itertools.chain.from_iterable(lstargs))
    return lstargs


print(lstfunc([1, 2, 3], 4, 5))
  

Но, к сожалению, это только [4, 5] повторный запуск.

В чем моя ошибка?

Ответ №1:

Нужный вам listcomp:

 lstargs = [x if isinstance(x, list) else [x] for x in lstargs]
  

чтобы воспроизвести целое list . Ваша попытка просто отфильтровала list s, она не выбирала между переносом и не переносом и создавала оба. Вам не нужно предварительно преобразовывать args в a list , чтобы быть понятным, поэтому вы можете упростить функцию до простого:

 def lstfunc(*args):
    # Save eager conversion to temp list by using genexpr instead of listcomp
    lstargs = (x if isinstance(x, list) else [x] for x in args)  # 
    return list(itertools.chain.from_iterable(lstargs))
  

Комментарии:

1. @Konrad: Всегда пожалуйста. Предупреждаю: для полностью универсального кода вам, вероятно, лучше импортировать Iterable ABC из collections.abc и изменить isinstance(x, list) на isinstance(x, Iterable) (возможно isinstance(x, Iterable) and not isinstance(x, (str, ByteString)) , если str bytes bytearray ожидаются аргументы // , хотя это довольно подробно), Поэтому вы не оборачиваете такие вещи, как tuple , set , случайные итераторы и т. Д. list Если кто-то звонит lstfunc((2, 3, 5), range(3), (x ** 2 for x in [10, 11, 12])) , вам, вероятно, нужен вывод [2, 3, 5, 0, 1, 2, 100, 121, 144] .

2. пожалуйста, найдите мой ответ ниже. Что вы думаете? Это хорошее решение или я должен знать о чем-то потенциально нежелательном?

Ответ №2:

После долгих мучений я нашел на самом деле самое простое и питоновское решение (я думаю)! Мне нужна была функция выше, чтобы создать одномерный список, чтобы передать его другой функции. Однако в этом нет необходимости. Мне просто нужен был оператор распаковки:

 def testfunc(*args):
    print(args)

testfunc(*[1, 2, 3], 4)
  

Вывод: (1, 2, 3, 4) .

Это решение автоматически сглаживает все значения в 1D чистую итерацию (кортеж, я думаю).

Комментарии:

1. Вот почему важно также объяснить вашу реальную проблему, а не просто вопрос о вашем предпринятом решении. См xyproblem.info

2. Спасибо, теперь я запомню :).