Условный вход в цикл for

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

def foo(arg1,sequence=None):
    # If possible, loop, else do it once
        if isinstance(sequence,(list,tuple)):
            for value in sequence:
                do_something(arg1)
        else:
            do_something(arg1)

Действия, которые я выполняю в цикле for, намного длиннее, чем это, и мне было интересно, какой подход вы обычно используете, чтобы этого избежать, если вы его избегаете. Я часто сталкиваюсь с этой проблемой и не придумал ничего, чтобы ее «решить».

Обновлено: Вопрос не является дубликатом Как в Python определить, является ли объект итерируемым?, как предлагается. Я не хочу вводить другое условие. Я хочу избежать повторения.

В чем смысл вашей петли for? Он не использует value, который переключается.

John Coleman 28.09.2018 14:24
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
1
63
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Стандартизируйте цикл, который является случаем по умолчанию, и преобразуйте свой единственный случай в повторяемый:

if not isinstance(sequence, (list, tuple)):
    sequence = [sequence]

for value in sequence:
    do_something(value)

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

if not isinstance(sequence, (list, tuple)):
    sequence = [sequence]
for value in sequence:
    ...

Распространенный способ Python - «попросить прощения вместо разрешения». То есть попробуйте рассматривать его как повторяемый, а если это не удается, предположите, что это не

try:
    for value in sequence:
         do_something(arg1)
except TypeError:
    do_something(arg1)

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

Если это приводит к повторению кода (а OP говорит, что кода там больше), то нет, это тоже не очень питонично.

deceze 28.09.2018 14:38

@deceze: я видел шаблон в стандартных библиотеках Python, поэтому он должен быть достаточно питоническим. Если есть больше кода, OP может сделать из него функцию (что должно быть сделано в любом случае, независимо от того, какой подход он выберет)

blue_note 28.09.2018 14:45

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

  1. функция, которая делает что-либо итерируемым, если это не список или кортеж (или что-то еще), например, помещая его в список или кортеж; а также
  2. функция, которая выполняет итерацию по элементам после того, как мы делаем ее итерируемой, и выполняет обработку, например:
def make_iterable(iterable):
    if not isinstance(iteable, (list,tuple)):
        return (iterable, )
    return iterable

def foo(arg1 ,sequence=None):
    for item in make_iterable(sequence):
        do_something(arg1, item)

Итак, теперь мы можем легко сделать итерируемыми больше вещей. Мы могли бы, например, вернуть пустой кортеж для None, так что None разрешен как способ избежать любой итерации:

def make_iterable(iterable):
    if iterable is None:
        return ()
    if not isinstance(iteable, (list,tuple)):
        return (iterable, )
    return iterable

Также легко повторное использование вышеупомянутого метода во всех видах методов, которые позволяют вводить как один объект, так и итерацию.

Однако учтите, что с вышеизложенным могут быть некоторые проблемы. Некоторые типы являются итерируемыми, но сами по себе не являются элементами, которые вы хотите перебирать: например, string является итерируемым (вы можете перебирать его символы). В этом случае Как в Python определить, является ли объект итерируемым? завершится успешно, но «распаковывать» строку - не лучшая идея. Но вы, возможно, не захотите перебирать строку, когда вы называете ее как foo(4, 'foobar'), а рассматриваете ее как отдельный элемент.

Другие вопросы по теме