Как работают переменные в Python
- Переменные, объекты и ссылки
- Идентификатор объекта (Object Identity)
- Работа с переменными
- Именование переменных
- Список зарезервированных слов
- Как объявить переменную
- Импорт переменной в Python
- Проверка существования переменной
- Удаление переменной
- Что означает звездочка перед переменной?
- Область видимости: локальные и глобальные переменные
- Статические переменные
Переменная — это именованная область памяти. После того как вы дали имя области, появляется возможность обращаться к данным, что в ней хранятся.
Каждый элемент данных в Python является объектом определенного типа или класса. Когда, в процессе выполнения программного кода, появляется новое значение, интерпретатор выделяет для него область памяти — то есть создаёт объект определенного типа (число, строка и т.д.). После этого Python записывает в свой внутренний список адрес этого объекта.
Но как теперь получить доступ к созданному объекту? 🤷♀️
Для этого и существуют переменные — они дают возможность удобно работать с объектами используя имена вместо адресов.
Простыми словами переменная в Python — это просто имя, прикрепленное к определенному объекту
Чтобы создать новую переменную в Python, ее нужно заранее инициализировать.
Инициализация переменной — это присвоение ей начального значения.
Для инициализации достаточно придумать переменной имя и присвоить значение через оператор =
.
a = 123
print(a)
> 123
print(type(a))
<class 'int'>
print(id(a))
1827204944
В примере выше мы создали переменную a
и присвоили ей значение 123
, далее вывели ее значение, тип и адрес объекта в памяти.
🍏 🍊 Приведем простую аналогию: Представьте, что у вас есть много непрозрачных бутылок, а сами вы занимаетесь производством фруктовых соков. Однажды вы выжали фрукты и в один сосуд налили апельсиновый сок, а во второй — яблочный. После этого ёмкости были запечатаны. Резонный вопрос: как теперь выяснить содержимое отдельно взятой бутылки?
Ответ: предварительно их подписать. Сделав это, вы будете точно знать, что находится в бутылках, а значит, сможете производить с ними дальнейшие операции: назначать цену, сортировать, отправлять на продажу и так далее.
Итак, ваш фреш-бизнес разросся, и для хранения соков пришлось арендовать склад, где каждая бутылка находится строго на своём месте. Теперь у вас есть ещё и специальные карточки: на каждой из них записаны наименование продукта и адрес этого продукта на складе. Когда требуется достать конкретную ёмкость с соком, вы смотрите на карточку, читаете номер ячейки, а затем идёте к обозначенному месту на складе и берёте оттуда нужную бутылку.
В данном примере:
- переменная — карточка продукции;
- адрес — это номер ячейки на складе;
- объект — сама ячейка;
- данные — бутылка с соком внутри.
Переменные, объекты и ссылки
Для понимания работы переменных, необходимо разобрать, что происходит, когда вы создаете новую переменную и присваиваете ей значение?
a = 100
В данном примере происходит следующее:
- создается объект типа
int
со значением100
; - создается переменная
a
; - в переменной
a
сохранится адрес (ссылка) на объект;
Важно: переменная в Python не хранит значение напрямую — она хранит лишь ссылку на объект
Теперь посмотрим что произойдет, если одной переменной присвоить другую переменную:
b = a
print(id(a))
> 1827204576
print(id(b))
> 1827204576
В данном примере Python не создает новый объект — он просто создает переменную, которая ссылается на тот же объект, что и переменная a
.
Предположим, что в какой-то момент вы захотели поменять значение переменной b
:
b = 500
print(id(a))
> 1827204576
print(id(b))
> 56754272
В данном примере Python создал новый объект типа int, и теперь переменная b ссылается на новый объект.
Рассмотрим еще один пример:
b = "tree"
print(id(b))
> 54134048
В этом примере создается новый объект типа str
, и переменная b
ссылается на новый объект.
b = "tree", переменная b теперь ссылается на новый объект строкового типа
На объект типа int
со значением 500
больше никто не ссылается. Следовательно, он больше не доступен и будет удален сборщиком мусора (тем самым освободив немного памяти).
Идентификатор объекта (Object Identity)
Идентификатор объекта — это адрес объекта в памяти.
В примерах выше мы вызывали функцию id()
. Эта функция возвращает число, которое является неизменным и уникальным для каждого объекта на протяжении его жизненного периода:
a = b = 1
print(id(a))
> 1593636784
print(id(b))
> 1593636784
print(id(1))
> 1593636784
Видно, что объект здесь всего один. А a
и b
— по-разному названные переменные, которые на него ссылаются. Проверить равенство идентификаторов можно с помощью оператора is
:
print(a is b)
> True
Работа с переменными
Именование переменных
В языке Python имя переменной должно состоять только из цифр, букв и знаков подчеркивания. И не должно начинаться с цифры.
Это жёсткий внутренний закон языка, помимо которого есть свод более мягких, но не менее важных правил, и они говорят нам:
- давайте переменным имена, которые описывают суть объекта;
- используйте единый стиль именования в рамках каждого проекта;
- старайтесь не создавать наименования длиннее пятнадцати символов;
Список зарезервированных слов
В каждом языке есть зарезервированные слова. Такие слова имеют специальное значение, и поэтому запрещены для использования в качестве имён переменных. Вот список зарезервированных слов для Python:
False, class, finally, is, return, None, continue, for, lambda, try, True, def, from, nonlocal, whileand, del, global, not, with, as, elif, if, or, yield, assert, else, import, pass, break, except, in, raise.
Как объявить переменную
В Питоне не требуется специального объявления переменных. В момент присваивания значения, объявление происходит автоматически. А присваивание выглядит так:
sitename = "Pythonchik"
Импорт переменной в Python
Чтобы импортировать переменную из другого файла, используем в начале текущего файла следующую конструкцию:
from <откуда_импортируем> import <что_импортируем>
Пример:
# файл main.py
space_ship = 'Millenium Falcon'
# файл second.py
from main import space_ship
print(space_ship)
> Millenium Falcon
Проверка существования переменной
Чтобы выяснить, есть ли в программе переменная (например cat
), ищем вхождение строки с её названием в словарях, возвращаемых функциями locals()
(локальная видимость) и globals()
(глобальная видимость):
if "cat" in locals():
# …
if "cat" in globals():
# …
Удаление переменной
Переменная удаляется, если передать её в качестве аргумента во встроенную функцию del()
:
please_dont = 'alive'
del(please_dont)
print(please_dont)
>
Traceback (most recent call last):
print(please_dont)
NameError: name 'please_dont' is not defined
Что означает звездочка перед переменной?
Символ *
перед именем переменной может означать несколько вещей.
1. Распаковывает итерируемый объект в аргументы функции.
status = ['open', 'close']
print(status)
> ['open', 'close']
print(*status)
> open close
2. Позволяет передавать в функцию переменное количество аргументов, запаковывая их в кортеж.
def summer(*terms):
sum = 0
for term in terms:
sum = sum + term
return sum
print(summer(2))
> 2
print(summer(3, 3))
> 6
print(summer(4, 43, 1))
> 48
3. Позволяет вложить итерируемый объект в новую коллекцию.
def setCreator(some_list):
return {*some_list[1:]}
weapons = ['bow', 'pike', 'sword', 'dagger']
print(setCreator(weapons))
> {'dagger', 'pike', 'sword'}
print(type(setCreator(weapons)))
> <class 'set'>
Область видимости: локальные и глобальные переменные
Сначала терминология. Область видимости или пространство имен — это место в программном коде, где переменной было присвоено значение.
Существуют три разные области видимости:
1 Локальная.
Если переменная была инициализирована внутри def
, то она локальная.
def localExample():
# x - локальная внутри localExample()
x = 5
2 Нелокальная.
Если внутри функции определена другая функция, то переменная внутри внешнего def
будет нелокальной для def
внутреннего. То есть сделать вот так не получится:
def nonlocalExample():
# x - локальная внутри nonlocalExample()
x = 5
def innerFunc():
x = x + 1
return x
return innerFunc()
print(nonlocalExample())
> UnboundLocalError: local variable 'x' referenced before assignment
Поэтому для корректной работы нужно использовать ключевое слово nonlocal
:
def nonlocalExample():
# x - локальная внутри nonlocalExample()
x = 5
def innerFunc():
nonlocal x
x = x + 1
return x
return innerFunc()
print(nonlocalExample())
> 6
3 Глобальная.
Переменная глобальна, если её присваивание производится за пределами всех def
.
num = 42
def globalExample(n):
res = n + num
return res
print(globalExample(1))
> 43
Статические переменные
Статическая переменная сохраняет свое значение между вызовами функций.
Звучит очень похоже на определение глобальной переменной, однако в том-то и дело, что статическая переменная может быть и локальной.
Самих по себе статических переменных в Питоне нет
Но их можно реализовать с помощью классов:
# сделаем питоновский аналог статической переменной
class staticVar:
i = 3
def incrementer():
staticVar.i = staticVar.i + 1
incrementer()
incrementer()
print(staticVar.i)
# Видно, что значение между вызовами функции сохраняется
> 5
-
Очень классные статьи.
Если переменная включает в себя содержимое двух переменных. Например,
a = b + c
, то создается новый блок в памяти или это будет ссылка на два блока?Операция
b + c
создает новый объект в памяти, иa
будет ссылаться на этот новый объект.Возникла проблема с примером из блока "Проверка существования переменной".
Проверял на следующем скрипте:
cat = 5 def test(): cat = 5 if "cat" in locals(): print('local yes') else: print('local no') if "cat" in globals(): print('global yes') else: print('global no')
Суть в том, что
if locals
выводит тот же результат, что иif globals
. Если глобальную переменнуюcat
заменить наdog
, оба ифа выведут "no".Функции
locals()
иglobals()
не отображают вообще все переменные, существующие в коде. Они отображают переменные в контексте вызова.Для более наглядного примера, подкорректирую код:
cat = 5 def test(): // код функции dog = 5 // внешний код (глобальный)
Относительно блока "внешний код",
cat
— глобальная и локальная,dog
— не существует, внешний код не может знать о переменных внутри функций.Относительно блока "код функции",
cat
— глобальная переменная, аdog
— локальная переменная.Данное поведение подробно рассматривалось в секции "Область видимости: локальные и глобальные переменные".
Спасибо, очень информативно!