Перейти к содержимому

Как создать переменные в цикле python

  • автор:

Операторы цикла

Цикл 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

Переменные — важная часть любого языка программирования. Они позволяют хранить, использовать и передавать данные.

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

Создание и присвоение значений

Создание переменной в Python 3 отличается от других языков программирования. Её не нужно заранее объявлять, указывать её тип, она создается в момент присваивания значения.

Чтобы создать переменную, используется символ равенства «=». Слева от которого пишут наименование, а справа — значение нужного типа. Пример:

name = "Александр" # Типа str (строка) age = 15 # Типа int (целое число)

Динамическая типизация

Такое создание переменных возможно благодаря динамической типизации.

Переменную не нужно объявлять заранее, потому что тип определяется по присвоенному значению, кроме того, при повторном присваивании значения другого типа, не нужно переопределять тип.

Множественное присваивание и обмен значениями

Python позволяет программисту присвоить одно и то же значение нескольким переменным:

a = b = c = 5 # Все (a, b и с) хранят значение 5

Кроме того, в отличие от других языков программирования Python позволяет обменять значения двух переменных —

a = 5, b = 3, с = 7 a, b = b, a # Теперь a = 3, а b = 5 a, b, c = c, a, b # Можно обменивать значения не только для двух

Такая операция возможна, потому что Python используется кортеж, в который помещает значения, чтобы можно было поменять их местами.

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

Имена

В именах переменных в Python 3 можно использовать только буквы, цифры и символы подчеркивания. Цифры можно использовать в любой части имени, кроме начала.

И если синтаксис накладывает на программиста мало ограничений, то IT сообщество требует «хороших» имён для переменных:

  • Имя должно описывать назначение. Так как код может перечитываться и изменяться множество раз, названия переменных должны быть такими, чтобы по ним можно было понять, что она хранит и для чего используется.
  • Не нужно использовать транслит. Если программист хочет создать переменную, хранящую возраст программиста, он должен писать не «vozrast», а «age». Это обусловлено тем, что английский — самый используемый язык в IT, название на английском поймут все, в любом случае, можно воспользоваться переводчиком.
  • Приемлемая длина. Имя должно не только отражать суть, но и быть коротким, слишком длинные названия увеличивают объем кода и ухудшают его восприятие.

Для создания хороших имён используются следующие методы:

  • CamelCase (верблюжий регистр): первое слово начинается с маленькой буквы, а следующие за ним с большой. В Python CamelCase принято использовать для имён классов. Например: WorkersOfFactory .
  • Snake Case: имя состоит из слов, разделенных символом подчеркивания «_», каждое слово пишут с маленькой буквы, например, hello_world . В Python Snake Case используется для имён функций, модулей и переменных. Такой стиль записи воспринимается лучше, чем CamelCase. Кроме того, он имеет несколько вариаций, которые не используются в Python: таких как запись через дефис «-» (kind-of-animals) и запись каждого слова с большой буквы (Sorted-Array-Of-Names).

Зарезервированные имена (ключевые слова)

Нельзя назвать переменную именем, которое уже зарезервировано, как ключевое слово. В Python есть около 33 зарезервированных имён: def, True, False, break и так далее.

Полный список ключевых слов можно посмотреть, набрав в интерпретаторе Python команду: help(«keywords») .

Вывод в консоль

Чтобы вывести переменную на экран, используют функцию print(). С её помощью можно вывести значение одной или нескольких переменных в форматированном выводе. Есть несколько вариантов синтаксиса вывода:

  • print(«<> — число, <> — слово».format(number, word)). Например, переменная number хранит значение 5, а word хранит «пять», тогда на экран выведется: «5 — число, пять — слово».
  • Можно обойтись без использования .format, достаточно писать составные части вывода через запятую: print(number, » — число», word, » — слово»).

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

Пустая переменная

Переменная — это ссылка на какой-то объект, она не может не содержать совсем ничего. Если программист хочет сделать его пустой (условно пустой), он присваивает ей значение None .

None используется в случаях, когда значение не определено, не существует. И хотя он не эквивалентен какому-либо значению типа bool, строке или числу, он также является объектом.

При необходимости, можно проверить содержимое переменной следующим образом:

a = None if a is None: print('значение равно None') else: print('другое значение')

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

Области видимости

В Python есть глобальная и локальная область видимости. Объявление переменных в разных областях видимости помогает избежать пересечения имён, открывает программисту новые уровни взаимодействий между ними и делает код более безопасным, делая невозможным несанкционированный доступ к механизмам работы функций.

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

Чтобы получить доступ к глобальной переменной из функции, необходимо использовать ключевое слово global, оно показывает интерпретатору, что нужно использовать находящуюся в глобальной области видимости. Кроме того, если функция не находит в своём теле нужную переменную, она автоматически ищет её в глобальной области видимости скрипта и использует.

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

В 3 версии Python было добавлено ключевое слово nonlocal . Оно позволяет получить доступ к переменной из локальной области видимости функции, при условии, что программист пытается получить доступ из другой вложенной функции. Пример:

def count(): n = 0 def inc(): n += 1 # Вызовется ошибка, функция не может получить доступ nonlocal n n += 1 # К n из внешней функции прибавится 1 return n inc() return n # будет равна 1 (если закомментировать строку с ошибкой)

Удаление

Для удаления переменной в Python 3 можно воспользоваться функцией del() , в качестве аргумента в которую нужно передать её имя. Пример:

a = 5 del(a) print(a) # Произойдёт исключение

Заключение

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

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

Как создать переменные в цикле 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='.')

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)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *