Форум сайта python.su
Здравствуйте, начал изучать Python, столкнулся с таким не понятным для меня поведением:
# -*- coding: utf8 -*-
def null(x):
x=[0]
def one(x):
x[0]=1
def test():
g=[5]
print g # выдаст [5]
null(g)
print g # выдаст [5], а ожидаю [0]
one(g)
print g # выдаст [1]
test()
Офлайн
DmitrijПочти так. Только не НЕЯВНО, а ЯВНО - это параметр x. Ему присваивается ссылка на новый лист
Есть единственное предположение, что в null() НЕЯВНО создается локальная переменная x, которая “затирает” передаваемый аргумент. Так ли это?
Офлайн
Просто в первом случае (one(x)) ты изменяешь список, на который ссылается g, а во втором (null(x)), ты присваиваешь локальной переменной x другой уже список (новый), на который g не ссылается, а ссылается на тот старый.
сорри, ответы почти совпали по времени:)
Отредактировано (Март 6, 2008 10:39:04)
Офлайн
Почитай про изменяемые и неизменяемые типы в питоне, это поможет разобраться в подобных ситуациях.
Офлайн
чтобы проще было разобраться, надо думать о том, что объекты во многих динамических языках ведут себя подобно “указателям” из старых языков, типо Си/Си++ и Паскаля. Т.е. чтобы изменить сам объект, нужно не переменную менять, а то на что она ссылается/“указывает”
в твоем случае надо просто сделать так:
def null(x): x[:] = [0]
Офлайн
Порадовало противопоставление “динамический” - “старый”:)
Офлайн
Спасибо большое за ответы. Вроде бы в голове немного прояснилось. Но для уверенности хочу уточнить, правильно ли я понял. Итак, по моим представлениям:
1) когда интерпретатор анализирует функцию, он создает список из аргументов фунции (в моем случае создается список из одной ссылки - ).
2) при выполнении кода Python связывает x и g (в начале выполнения функций x указывает на тот же объект, что и g).
3) в функции null() x переопределяется и начинает указывать на новый объект, а связь со старым (на который указывает g) теряется.
Правильно ли я понял?
Офлайн
можно я расскажу в объеме моего знания интерпретатора, а знающие люди поправят?
в питоне большое значение имеют пространства имен. фактически это словари связывающие имена переменных (x, y, z) с некоторыми объектами. Есть объекты изменяемые (списки и словари например) и неизменяемые (числа и строки). Изменяемые – это те, содержимое которых можно изменить. при этом связь между именем переменной и питон-объектом не разрывается. Неизменяемые – это те, которые живут в неизменном виде. Поэтому когда идет присваивание какого-то объекта переменной, то связь в пространстве имен обновляется. И тоже самое имя (x) начинает указывать на другой объект. Объекты в питоне при этом глобальны. Локальны только пространства имен.
Глобальная переменная g живет в глобальном пространстве имен скрипта.
Когда вызывается функция null() указатель на глобальную переменную g передается в функцию и связывается с локальным именем x. Потом в этой функции значение присваивается локальному имени x для этой функции. Ссылка на глобальную переменную g исчезает. При возврате из функции имя x перестает существовать (осуществляется сборка мусора). Поэтому чтобы изменить глобальную g нужно явно вернуть значение из null, типа так:
def null():
return
g = null()
В случае с функцией one все проще. Связь между объектом g и x не разрывается. потому что список – это изменяемый объект. поэтому меняется первый элемент списка (с индексом 0), но сам список остается тем же самым объектом.
Отредактировано (Март 6, 2008 23:54:24)
Офлайн
Dmitrijдумаю в целом правильно.
Спасибо большое за ответы. Вроде бы в голове немного прояснилось. Но для уверенности хочу уточнить, правильно ли я понял. Итак, по моим представлениям:
1) когда интерпретатор анализирует функцию, он создает список из аргументов фунции (в моем случае создается список из одной ссылки - ).
2) при выполнении кода Python связывает x и g (в начале выполнения функций x указывает на тот же объект, что и g).
3) в функции null() x переопределяется и начинает указывать на новый объект, а связь со старым (на который указывает g) теряется.
Правильно ли я понял?
Офлайн
Хорошо. Спасибо еще раз за ответы. Пойду продолжу изучение.
Офлайн