Уведомления

Группа в Telegram: @pythonsu

#1 Март 6, 2008 09:18:00

Dmitrij
От:
Зарегистрирован: 2008-03-06
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Изменение аргумента функции

Здравствуйте, начал изучать 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()
Не могу понять, с чем связано то, что null() не меняет аргумент, а one() - меняет. Есть единственное предположение, что в null() НЕЯВНО создается локальная переменная x, которая “затирает” передаваемый аргумент. Так ли это?



Офлайн

#2 Март 6, 2008 10:36:15

Александр Кошелев
От: Москва
Зарегистрирован: 2007-02-03
Сообщения: 1724
Репутация: +  2  -
Профиль   Отправить e-mail  

Изменение аргумента функции

Dmitrij
Есть единственное предположение, что в null() НЕЯВНО создается локальная переменная x, которая “затирает” передаваемый аргумент. Так ли это?
Почти так. Только не НЕЯВНО, а ЯВНО - это параметр x. Ему присваивается ссылка на новый лист



Офлайн

#3 Март 6, 2008 10:37:56

poltergeist
От:
Зарегистрирован: 2007-02-28
Сообщения: 522
Репутация: +  0  -
Профиль   Отправить e-mail  

Изменение аргумента функции

Просто в первом случае (one(x)) ты изменяешь список, на который ссылается g, а во втором (null(x)), ты присваиваешь локальной переменной x другой уже список (новый), на который g не ссылается, а ссылается на тот старый.

сорри, ответы почти совпали по времени:)



Отредактировано (Март 6, 2008 10:39:04)

Офлайн

#4 Март 6, 2008 16:01:06

Viper
От:
Зарегистрирован: 2006-11-08
Сообщения: 137
Репутация: +  0  -
Профиль   Отправить e-mail  

Изменение аргумента функции

Почитай про изменяемые и неизменяемые типы в питоне, это поможет разобраться в подобных ситуациях.



Офлайн

#5 Март 6, 2008 18:02:42

Frenzy
От:
Зарегистрирован: 2007-11-10
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Изменение аргумента функции

чтобы проще было разобраться, надо думать о том, что объекты во многих динамических языках ведут себя подобно “указателям” из старых языков, типо Си/Си++ и Паскаля. Т.е. чтобы изменить сам объект, нужно не переменную менять, а то на что она ссылается/“указывает”

в твоем случае надо просто сделать так:

def null(x):
    x[:] = [0]



Офлайн

#6 Март 6, 2008 18:17:15

Александр Кошелев
От: Москва
Зарегистрирован: 2007-02-03
Сообщения: 1724
Репутация: +  2  -
Профиль   Отправить e-mail  

Изменение аргумента функции

Порадовало противопоставление “динамический” - “старый”:)



Офлайн

#7 Март 6, 2008 18:33:41

Dmitrij
От:
Зарегистрирован: 2008-03-06
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Изменение аргумента функции

Спасибо большое за ответы. Вроде бы в голове немного прояснилось. Но для уверенности хочу уточнить, правильно ли я понял. Итак, по моим представлениям:
1) когда интерпретатор анализирует функцию, он создает список из аргументов фунции (в моем случае создается список из одной ссылки - ).
2) при выполнении кода Python связывает x и g (в начале выполнения функций x указывает на тот же объект, что и g).
3) в функции null() x переопределяется и начинает указывать на новый объект, а связь со старым (на который указывает g) теряется.
Правильно ли я понял?



Офлайн

#8 Март 6, 2008 23:52:06

bialix
От:
Зарегистрирован: 2006-07-13
Сообщения: 774
Репутация: +  1  -
Профиль   Отправить e-mail  

Изменение аргумента функции

можно я расскажу в объеме моего знания интерпретатора, а знающие люди поправят?

в питоне большое значение имеют пространства имен. фактически это словари связывающие имена переменных (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)

Офлайн

#9 Март 6, 2008 23:54:58

bialix
От:
Зарегистрирован: 2006-07-13
Сообщения: 774
Репутация: +  1  -
Профиль   Отправить e-mail  

Изменение аргумента функции

Dmitrij
Спасибо большое за ответы. Вроде бы в голове немного прояснилось. Но для уверенности хочу уточнить, правильно ли я понял. Итак, по моим представлениям:
1) когда интерпретатор анализирует функцию, он создает список из аргументов фунции (в моем случае создается список из одной ссылки - ).
2) при выполнении кода Python связывает x и g (в начале выполнения функций x указывает на тот же объект, что и g).
3) в функции null() x переопределяется и начинает указывать на новый объект, а связь со старым (на который указывает g) теряется.
Правильно ли я понял?
думаю в целом правильно.



Офлайн

#10 Март 7, 2008 12:06:14

Dmitrij
От:
Зарегистрирован: 2008-03-06
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Изменение аргумента функции

Хорошо. Спасибо еще раз за ответы. Пойду продолжу изучение.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version