Хороший стиль для ввода переменных python в цикле

У меня есть фон на С++, и я изучаю Python. Я пишу код, который должен извлечь конкретное значение из цикла for:

seventh_value = None   # ** my question is about this line
for index in range(1, 10):
    value = f(index)
    # we have a special interest in the seventh value
    if index == 7:
        seventh_value = value
    # (do other things with value here)

# make use of seventh_value here

В С++ мне нужно объявить седьмое значение перед циклом for, чтобы гарантировать, что его область действия не ограничивается циклом for. В Python мне не нужно это делать. Мой вопрос заключается в том, хороший ли стиль, чтобы опустить начальное назначение на седьмое_значение.

Я понимаю, что если цикл не повторяется не менее 7 раз, я могу избежать использования NameError, назначая до седьмого значения до цикла. Предположим, что ясно, что он будет итерации как минимум в 7 раз (как в приведенном выше примере, где я записал 10 итераций с жестким кодированием).

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

Код, который я написал выше, мне кажется ясным, но я думаю, что просто вижу его глазами С++.

Ответ 1

Это прекрасный подход, чтобы установить значение None перед циклом for. Не волнуйся так сильно. Лично я чувствую, что код читается кем-то, кто вообще не имеет понятия - это нормально.

Говоря, есть немного лучший (питонический) способ избежать проблемы вообще. Примечание, что следующее не ничего не делает со значением на каждой итерации - только часть "особого интереса". Кроме того, я предполагаю, что f(..) не вызывает никаких побочных эффектов (например, изменения состояний переменных вне (например, глобальных переменных). Если это так, строка ниже определенно не для вас.

seventh_value = next(f(i) for i in range(1,10) if i == 7)

Вышеуказанная конструкция выполняется до я == 7 и вызывает f(i) только тогда, когда я = 7 никогда больше.

Ответ 2

Это лишь частично вопрос стиля. Вам нужно что-то сделать, чтобы ваш код не повышал (uncaught) NameError после цикла, поэтому ваши два варианта:

  • Убедитесь, что NameError не может произойти, сделав безусловное присвоение seventh_value.

  • Оберните код, который обращается к seventh_value в блоке try, чтобы поймать и (предположительно) игнорировать возможный NameError.

Посмотрите с этой точки зрения и, не зная больше о своем коде, я думаю, вы согласитесь, что предпочтительнее # 1.

Ответ 3

Если вы уверены, что seventh_value должен быть установлен, и вы рассчитываете на него в своей программной логике, вы даже можете потерять код с помощью NameError и записать его без предварительного определения seventh_value.

Если вы уверены, что seventh_value не может быть установлен, когда весь код работает нормально, вы должны, вероятно, определить seventh_value, как в примере, и проверить позже, если он был установлен вообще.

Ответ 4

Вы можете сделать это именно так, как вы предлагаете, и если вы попробуете его, вы обнаружите, что он работает именно так, как вы хотите.

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

results = []
for index in range(1, 10):
    value = f(index)
    # (do other things with value here)

    results.append(value)     

seventh_value = results[6] #6 because index 1 is at location 0 in the list.
# make use of seventh_value here

Теперь, когда у вас есть простой цикл for, он может быть легко реорганизован в понимание списка:

results = [f(index) for index in range(1, 10)]

for value in results:
    # (do other things with value here)

seventh_value = results[7]
# make use of seventh_value here

Если вы решите пойти так далеко, будет зависеть от того, насколько сложна ваша (do other things with value here).