Найти - Пользователи
Полная версия: Изменение аргумента функции
Начало » Python для новичков » Изменение аргумента функции
1 2
Dmitrij
Здравствуйте, начал изучать 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, которая “затирает” передаваемый аргумент. Так ли это?
Александр Кошелев
Dmitrij
Есть единственное предположение, что в null() НЕЯВНО создается локальная переменная x, которая “затирает” передаваемый аргумент. Так ли это?
Почти так. Только не НЕЯВНО, а ЯВНО - это параметр x. Ему присваивается ссылка на новый лист
poltergeist
Просто в первом случае (one(x)) ты изменяешь список, на который ссылается g, а во втором (null(x)), ты присваиваешь локальной переменной x другой уже список (новый), на который g не ссылается, а ссылается на тот старый.

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

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

в питоне большое значение имеют пространства имен. фактически это словари связывающие имена переменных (x, y, z) с некоторыми объектами. Есть объекты изменяемые (списки и словари например) и неизменяемые (числа и строки). Изменяемые – это те, содержимое которых можно изменить. при этом связь между именем переменной и питон-объектом не разрывается. Неизменяемые – это те, которые живут в неизменном виде. Поэтому когда идет присваивание какого-то объекта переменной, то связь в пространстве имен обновляется. И тоже самое имя (x) начинает указывать на другой объект. Объекты в питоне при этом глобальны. Локальны только пространства имен.

Глобальная переменная g живет в глобальном пространстве имен скрипта.

Когда вызывается функция null() указатель на глобальную переменную g передается в функцию и связывается с локальным именем x. Потом в этой функции значение присваивается локальному имени x для этой функции. Ссылка на глобальную переменную g исчезает. При возврате из функции имя x перестает существовать (осуществляется сборка мусора). Поэтому чтобы изменить глобальную g нужно явно вернуть значение из null, типа так:

def null():
return

g = null()


В случае с функцией one все проще. Связь между объектом g и x не разрывается. потому что список – это изменяемый объект. поэтому меняется первый элемент списка (с индексом 0), но сам список остается тем же самым объектом.
bialix
Dmitrij
Спасибо большое за ответы. Вроде бы в голове немного прояснилось. Но для уверенности хочу уточнить, правильно ли я понял. Итак, по моим представлениям:
1) когда интерпретатор анализирует функцию, он создает список из аргументов фунции (в моем случае создается список из одной ссылки - ).
2) при выполнении кода Python связывает x и g (в начале выполнения функций x указывает на тот же объект, что и g).
3) в функции null() x переопределяется и начинает указывать на новый объект, а связь со старым (на который указывает g) теряется.
Правильно ли я понял?
думаю в целом правильно.
Dmitrij
Хорошо. Спасибо еще раз за ответы. Пойду продолжу изучение.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB