Понимание списка Python с фиктивными именами, идентичными имени итератора: неблагоразумно?


Скажем, я составляю список понимания, который выглядит примерно так:

i = range(5)
a = [f(i) for i in i]

Для некоторой функции f. Даст ли использование фиктивного имени, идентичного итератору, когда-либо неожиданные результаты? Иногда у меня есть имена переменных, которые являются отдельными буквами, и мне удобнее придерживаться одной и той же буквы, а не назначать новую, например [f(x) for x in x] вместо [f(i) for i in x] (например, если буква итератора x является значимой , я задам себе вопрос, что за черт i есть).

2 8

2 ответа:

TL; DR: это безопасно технически, но это плохой выбор стилистически.

В понимании списка, перед привязкой свободной переменной цикла for к любому объекту, Python будет использовать код операции GET_ITER на iterable, чтобы получить итератор. Это делается только один раз в начале цикла.

Поэтому в теле "цикла" понимания списка (который фактически создает область в Python 3), Вы можете повторно связать имя, которое первоначально указывало на повторяется без каких-либо последствий. Итерация имеет дело непосредственно со ссылкой на итератор , и неважно, имеет ли он имя в области видимости. То же самое должно быть верно и в Python 2, хотя детали реализации области действия различны: имя коллекции будет потеряно после понимания, так как имя переменной цикла останется привязанным к конечному элементу итерации.

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

[f(x) for x in xs]

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

Однако это приводит к гораздо более важному моменту. Зачем использовать такое имя, как i, j, или x вообще? Использование однобуквенных имен переменных приводит к путанице и неоднозначности. Вместо этого используйте имя переменной, которое ясно передает ваше намерение.

Или, если у вас нет необходимости вообще для значений в iterable вашего перебора(например. Вы просто хотите повторить блок кода определенное количество раз), используйте переменную" выбрасывания", _, чтобы донести до читателя вашего кода, что значение не важно и должно быть проигнорировано.

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

Потому что, в конце концов, вы бы предпочли поддерживать такой код

[str(x) for x in x]

Или это?

[str(user_id) for user_id in user_ids]