Операторы цикла
Цикл for, также называемый циклом с параметром, в языке Питон богат возможностями. В цикле for указывается переменная и множество значений, по которому будет пробегать переменная. Множество значений может быть задано списком, кортежем, строкой или диапазоном.
Вот простейший пример использования цикла, где в качестве множества значений используется кортеж:
i = 1
for color in 'red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'violet':
print(i,'-th color of rainbow is ', color, sep = '')
i += 1
В этом примере переменная color последовательно принимает значения ‘red’, ‘orange’ и т.д. В теле цикла выводится сообщение, которое содержит название цвета, то есть значение переменной color, а также номер итерации цикла число, которое сначала равно 1, а потом увеличивается на один (инструкцией i += 1 с каждым проходом цикла.
В списке значений могут быть выражения различных типов, например:
for i in 1, 2, 3, 'one', 'two', 'three':
print(i)
При первых трех итерациях цикла переменная i будет принимать значение типа int, при последующих трех — типа str.
Обьявление переменных в цикле python
Реально ли сделать механизм по которому, цикл пробегаться по словарю и объявляет переменную с именем ключа и которой присваивается соответствующее значения из этого же словаря. P.S. нужно для написания модуля который предназначен для реализации мультиязычности в программе, т.е. доступ к соответствующему словарю языка который берется из файла json и выводу из него сообщения по ключу(mess_id).
Отслеживать
задан 9 ноя 2017 в 0:08
67 2 2 серебряных знака 5 5 бронзовых знаков
Python и локальные переменные внутри цикла
Нет ли способа поиметь в Python’е локальные переменные внутри циклов? Такие, которые не будут загромождать область видимости вовне? Иначе, когда код разрастается на экран-другой, понимать, что к чему, становится всё труднее.
Я знаю, что для хорошего кода тела циклов выносят в функции и методы. Однако клепаемый код — это, зачастую, одноразовые скрипты для статистических расчётов. Которые пишутся в духе «посмотрим на графики от предыдущей итерации и добавим/удалим пяток строк». О проектировании часто речь не идёт вообще, потому как я часто не знаю, что буду писать дальше.
Python здесь — это замена MATLABу.
И таки да, нет ли способа сделать так, чтобы переменные внутри циклов были локальными?

Yak ★
25.09.13 17:41:35 MSK
← 1 2 →

Прямых способов нет. Но есть возможность например в начале тела цикла создавать объект пустого класса, дальше напихивать в него поля, а в конце тела цикла его убивать.
AIv ★★★★★
( 25.09.13 17:57:58 MSK )
нет ли способа сделать так, чтобы переменные внутри циклов были локальными?
Есть. Взять вместо прыщеподелки любой вменяемый язык программирования.
anonymous
( 25.09.13 17:58:54 MSK )
А какая разница, локальные они для цикла или локальные для функции. Это же не Си, в Питоне их можно использовать повторно для следующего цикла.
kvap ★
( 25.09.13 18:02:09 MSK )
Ответ на: комментарий от anonymous 25.09.13 17:58:54 MSK

Это например какой же?
Yak ★
( 25.09.13 18:07:31 MSK ) автор топика
Ответ на: комментарий от AIv 25.09.13 17:57:58 MSK

Прямых способов нет. Но есть возможность например в начале тела цикла создавать объект пустого класса, дальше напихивать в него поля, а в конце тела цикла его убивать.
Можете показать кодом?
Yak ★
( 25.09.13 18:14:58 MSK ) автор топика
Ответ на: комментарий от Yak 25.09.13 18:14:58 MSK

class Dummy: pass . for . : ns = Dummy() ns.a = . b = . ns.a . . del ns
ЛИСП же! Не связывайтесь с лавсанчегом, он упорот чуть более чем полностью.
AIv ★★★★★
( 25.09.13 18:20:21 MSK )
Ответ на: комментарий от AIv 25.09.13 17:57:58 MSK
И зачем там объект?
anonymous
( 25.09.13 18:26:36 MSK )
Ответ на: комментарий от AIv 25.09.13 18:20:21 MSK
Это не лавсан, да и упорот он не более иных сиплюсплюсников, явовщиков, хаскелистов, эрлангистов и т.д. (список можно продолжать).
dave ★★★★★
( 25.09.13 18:27:05 MSK )
Ответ на: комментарий от AIv 25.09.13 18:20:21 MSK
А разве ‘with’ не делает как раз примерно того же — объект, который убивается при завершении.
alpha ★★★★★
( 25.09.13 18:29:40 MSK )
Ответ на: комментарий от alpha 25.09.13 18:29:40 MSK

цикл не является выражением.
aedeph_ ★★
( 25.09.13 18:35:14 MSK )
Ответ на: комментарий от aedeph_ 25.09.13 18:35:14 MSK

Это я знаю. Я только не знаю, как его правильно делать выражением. Неужели и правда втыкать класс-затычку как у AIv?
Yak ★
( 25.09.13 18:36:19 MSK ) автор топика
Ответ на: комментарий от Yak 25.09.13 18:36:19 MSK

Можно свой оператор assignment’а написать, возвращающий строчку для exec’а, который будет кроме просто «=» дампать переменные в специальные Set’ы, а также свой for, который будет подчищать за собой.
Но разумеется, так делать не нужно.
aedeph_ ★★
( 25.09.13 18:42:04 MSK )
Сам себе придумал проблему, сам её и решай, мы-то тут при чём.
anonymous
( 25.09.13 18:45:31 MSK )

В Perl’ике перед переменной достаточно поставить my , например.
Наверняка в питоне есть что-то подобное.
makyrros
( 25.09.13 18:47:40 MSK )
Ответ на: комментарий от Yak 25.09.13 18:36:19 MSK
Зачем тебе класс-затычка? Сделай «del a, b, c» после цикла и радуйся.
anonymous
( 25.09.13 18:49:30 MSK )
Ответ на: комментарий от anonymous 25.09.13 18:49:30 MSK

Да, но а если их там с десяток?
Yak ★
( 25.09.13 18:52:05 MSK ) автор топика
Ответ на: комментарий от Yak 25.09.13 18:52:05 MSK
Выдели в функции циклы.
zz ★★★★
( 25.09.13 18:57:31 MSK )
Ответ на: комментарий от aedeph_ 25.09.13 18:35:14 MSK
Я сразу скажу что я чайник, и не понимаю.
Если допустим я сделаю так:
with a() as A: for: do_smth(A)

то для A по окончании будет вызываться __exit__(), который может это A прибивать. И вроде бы это то же самое, что предлагает AIv . Нет?
alpha ★★★★★
( 25.09.13 18:58:17 MSK )
Последнее исправление: alpha 25.09.13 18:58:39 MSK (всего исправлений: 1)
Ответ на: комментарий от zz 25.09.13 18:57:31 MSK

Тогда будет немного тяжелее перекраивать код на ходу.
Yak ★
( 25.09.13 18:58:36 MSK ) автор топика
Ответ на: комментарий от zz 25.09.13 18:57:31 MSK
def mahlopp: for blah mahloop() def mahotherlopp: for blah mahotherlopp()
Можно прямо в теле метода локальные функции делать.
zz ★★★★
( 25.09.13 18:59:41 MSK )
Ответ на: комментарий от zz 25.09.13 18:59:41 MSK
А вообще можно даже одно имя пользовать.
zz ★★★★
( 25.09.13 19:01:30 MSK )
Ответ на: комментарий от Yak 25.09.13 18:58:36 MSK
zz ★★★★
( 25.09.13 19:01:44 MSK )
Переменные внутри циклов и так локальные. Тебе нужен аналог let из лиспа или что? Такого нет. И в питоне это особо вообще никак не мешает — если тебе нужны такие же имена после цикла: вариант с del’ом уже предложили, второй вариант — берешь и переопределяешь переменные.
alienclaster ★★★
( 25.09.13 19:55:53 MSK )

# coding: utf-8 # быдлокодим def foo(): while 1: old_globals = globals().keys() yield new_globals = globals().keys() for var in new_globals: if var not in old_globals: globals().pop(var) yield foo = iter(foo()) # используем next(foo) for i in xrange(5): j = k = i next(foo) # проверяем print i, j, k # профит!
Virtuos86 ★★★★★
( 25.09.13 20:33:56 MSK )
Ответ на: комментарий от alienclaster 25.09.13 19:55:53 MSK

Переменные внутри циклов и так локальные.
Тело цикла не является блоком кода, вводящим отдельное локальное пространство имен. Поэтому переменные в цикле определяются в том же неймспейсе, где определен цикл (то бишь переменная цикла). Если циклы находятся на уровне модуля (как у ТС), то есть в глобальном пространстве имен, то и их переменные глобальны. Такое же поведение у list comprehensions было, поправили не помню в какой версии.
Virtuos86 ★★★★★
( 25.09.13 20:43:38 MSK )
Последнее исправление: Virtuos86 25.09.13 20:45:17 MSK (всего исправлений: 1)
Ответ на: комментарий от Virtuos86 25.09.13 20:33:56 MSK

опять же, на немного лохматых версиях питоши вместо
Virtuos86 ★★★★★
( 25.09.13 20:49:44 MSK )
Ответ на: комментарий от Virtuos86 25.09.13 20:33:56 MSK

Неплохо, однако предыдущее состояние переменных он не возвращает, только выкидывает новые.
aedeph_ ★★
( 26.09.13 00:05:46 MSK )
Как вариант делай приставку к переменным local_ Только не забывай их обнулять. Будешь знать что в local_ нету ничего важного и не страшно если переменная с таким именем уже встречалась. Как я понял тебе же главное не обратится к уже существующей переменной или не переопределить уже существующею? тогда прокатит. Помоему самый простой вариант.
local_num, local_f = '', ''
matrixd ★
( 26.09.13 02:57:22 MSK )
ТС, тебе не стыдно? Смотри сколько говнокода уже сгенерировано. Если портянка большая, то ответ напрашивается сам собой — разбить. Если это одноразовая большая портянка, то опять всё очевидно — забить. Проблема яйца выеденного не стоит.
anonymous
( 26.09.13 03:02:27 MSK )
Ответ на: комментарий от aedeph_ 26.09.13 00:05:46 MSK

Предыдущее? Хех, тогда только в функции циклы выносить, иначе костыли будут шикарные.
import copy a, b, c = 1, 2, 3 code = '''\ a, b, c = 4, 5, 6 ''' exec code in copy.deepcopy(globals()) print a, b, c
Код не проверял, не на чем. Но сомнительно, что глубокое копирование будет хорошо работать на реальных пользовательских объектах, как на сферических примерах.
Virtuos86 ★★★★★
( 26.09.13 04:34:40 MSK )
Ответ на: комментарий от Virtuos86 25.09.13 20:43:38 MSK
Тело цикла не является блоком кода, вводящим отдельное локальное пространство имен. Поэтому переменные в цикле определяются в том же неймспейсе, где определен цикл (то бишь переменная цикла).
Да, действительно — это я фигню сказал, хотя сказал там же, что let отсутствует.
Если циклы находятся на уровне модуля (как у ТС), то есть в глобальном пространстве имен, то и их переменные глобальны.
Не очень могу представить, зачем в библиотеки циклам бы находиться внутри модуля, а не в функции / классе.
Такое же поведение у list comprehensions было, поправили не помню в какой версии
alienclaster ★★★
( 26.09.13 05:03:59 MSK )
Ответ на: комментарий от alienclaster 26.09.13 05:03:59 MSK

Не очень могу представить, зачем в библиотеки циклам бы находиться внутри модуля, а не в функции / классе.
ТС написал, зачем ему. Хотя настоящий ответ — лень, первейший источник быдлокода :->.
Но-но, без розжига. Не все так однозначно. Те же генераторные выражения такой болезнью изначально не страдали. А l.c. это практически сахар для цикла for с накопителем, потому и копирует его поведение. А оно вот такое. Короче, один из python tips.
Virtuos86 ★★★★★
( 26.09.13 05:32:45 MSK )
Такие, которые не будут загромождать область видимости вовне? Иначе, когда код разрастается на экран-другой, понимать, что к чему, становится всё труднее.
нихрена себе трудней понимать. То, каким образом это решается в питоне намного усложнит код, чем если б ты просто с другой стороны подошел к решению.
P.S. за тролленг питона разве что зачёт. «Код разрастается» — ну, нашел причину)
anonymous
( 26.09.13 05:38:38 MSK )
Ответ на: комментарий от Virtuos86 26.09.13 04:34:40 MSK

Не не не, никакого deepcopy, это полный Содом. Изменение мутабельных (мутация того же объекта) трогать не надо, его могли, и это даже очень вероятно, изменять сознательно. А вот новый assignment в блоке, который затёр старый, следует откатить. Разумеется для питона этого сделать без переопределения (в голове, хотя бы) «=» не выйдет, поэтому и быдлоязычок, и говноскоупинг.
def x(): a = False def y(): print a a = True return y
aedeph_ ★★
( 26.09.13 06:31:35 MSK )
Ответ на: комментарий от Virtuos86 26.09.13 05:32:45 MSK

это практически сахар для цикла for с накопителем
А почему не сахар над list(x for x in iterable)?
aedeph_ ★★
( 26.09.13 06:33:41 MSK )
Ответ на: комментарий от aedeph_ 26.09.13 06:33:41 MSK

Потому что list(x for x in iterable) это сахар над list((x for x in iterable)), а генераторные выражения появились намного позднее генераторов списков.
Virtuos86 ★★★★★
( 26.09.13 10:12:00 MSK )
Последнее исправление: Virtuos86 26.09.13 10:12:41 MSK (всего исправлений: 1)
Ответ на: комментарий от aedeph_ 26.09.13 06:31:35 MSK

Теперь понял. Однако, в питоне есть блоки кода — это функции, определяемые инструкциями «def» и «lambda». Если нужна функциональность блоков кода, то надо использовать их, а не пенять, что вещи, не предназначенные для этого, не удается использовать не по назначению. Теперь что касается переопределения «=». Есть два пути. Первый, чернокнижный: можно написать свой кодек, который при парсинге и разборе исходника будет запоминать определяемые переменные и бить по рукам при их повторном переопределении. Все это отслеживается на этапе даже не «компиляции», а чуть пораньше, и динамику не учитывает. Не говоря уже о том, что это уже и не питон будет. Кодек — это то, что указывается в модуле как
В принципе, для себя вполне приемлемый вариант.
Второй: наподобие того, что предложил AIv. Пишем свой класс-неймспейс, переопределяем для него __getattribute__/__setattr__, создаем инстанс этого класса (назовем его «let»), переменные регистрируем как атрибуты let. Дальше контролируем доступ к ним как угодно. Я такое видел, имхо неизящно и избыточно.
Virtuos86 ★★★★★
( 26.09.13 10:48:45 MSK )
Ответ на: комментарий от Virtuos86 26.09.13 10:12:00 MSK

Странно, всегда считал, что genexpr появился за одну минорную версию до lc, но был неправ, 2.0 (2000) vs 2.4 (2002)
Как создать переменные в цикле python
Цикл for , также называемый циклом с параметром, в языке Питон богат возможностями. В цикле for указывается переменная и множество значений, по которому будет пробегать переменная. Множество значений может быть задано списком, кортежем, строкой или диапазоном.
Вот простейший пример использования цикла, где в качестве множества значений используется кортеж:
i = 1 for color in 'red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'violet': print('#', i, ' color of rainbow is ', color, sep = '') i += 1
В этом примере переменная color последовательно принимает значения ‘red’ , ‘orange’ и т.д. В теле цикла выводится сообщение, которое содержит название цвета, то есть значение переменной color , а также номер итерации цикла число, которое сначала равно 1, а потом увеличивается на один (инструкцией i += 1 с каждым проходом цикла.
Инструкция i += 1 эквивалентна конструкции i = i + 1 (это просто сокращенная запись). Такую сокращенную запись можно использовать для всех арифметических операций: *= , -= , /= , %= .
В списке значений могут быть выражения различных типов, например:
for i in 1, 2, 3, 'one', 'two', 'three': print(i)
При первых трех итерациях цикла переменная i будет принимать значение типа int , при последующих трех — типа str .
2. Функция range
Как правило, циклы for используются либо для повторения какой-либо последовательности действий заданное число раз, либо для изменения значения переменной в цикле от некоторого начального значения до некоторого конечного.
Для повторения цикла некоторое заданное число раз n можно использовать цикл for вместе с функцией range :
for i in range(4): # равносильно инструкции for i in 0, 1, 2, 3: # здесь можно выполнять циклические действия print(i) print(i ** 2) # цикл закончился, поскольку закончился блок с отступом print('Конец цикла')
В качестве n может использоваться числовая константа, переменная или произвольное арифметическое выражение (например, 2 ** 10 ). Если значение n равно нулю или отрицательное, то тело цикла не выполнится ни разу.
Функция range может также принимать не один, а два параметра. Вызов range(a, b) означает, что индексная переменная будеть принимать значения от a до , то есть первый параметр функции range , вызываемой с двумя параметрами, задает начальное значение индексной переменной, а второй параметр — первое значение, которое индексная переменная принимать не будет. Если же a ≥ b , то цикл не будет выполнен ни разу. Например, для того, чтобы просуммировать значения чисел от 1 до n можно воспользоваться следующей программой:
sum = 0 n = 5 for i in range(1, n + 1): sum += i print(sum)
В этом примере переменная i принимает значения 1, 2, . n , и значение переменной sum последовательно увеличивается на указанные значения.
Наконец, чтобы организовать цикл, в котором индексная переменная будет уменьшаться, необходимо использовать функцию range с тремя параметрами. Первый параметр задает начальное значение индексной переменной, второй параметр — значение, до которого будет изменяться индексная переменная (не включая его!), а третий параметр — величину изменения индексной переменной. Например, сделать цикл по всем нечетным числам от 1 до 99 можно при помощи функции , а сделать цикл по всем числам от 100 до 1 можно при помощи .
Более формально, цикл при d > 0 задает значения индексной переменной i = a , i = a + d , i = a + 2 * d и так для всех значений, для которых i < b . Если же d < 0 , то переменная цикла принимает все значения i >b .
3. Настройка функции print()
По умолчанию функция print() принимает несколько аргументов, выводит их через пробел, после чего ставит перевод строки. Это поведение можно изменить, используя именованные параметры sep (разделитель) и end (окончание).
print(1, 2, 3) print(4, 5, 6) print(1, 2, 3, sep=', ', end='. ') print(4, 5, 6, sep=', ', end='. ') print() print(1, 2, 3, sep='', end=' -- ') print(4, 5, 6, sep=' * ', end='.')