Блог Толика Вострякова

Живой опыт программирования, Python, Django, современные языки и немного фотографий
Блог - новые записи и ссылки (Atom)

Передача параметров по ссылке в Питоне -

Мне нужно было передать в функцию параметр, в функции он изменяется и снаружи функции видно изменение. То есть фактически передать в функцию переменную по ссылке. Оказалось в Питоне с этим хитро. Есть изменяемые и неизменяемые переменные. Зависит от типа. Например, строки неизменяемый тип, а списки изменяемый. Соответственно строки передаются в функцию по значению, а список по ссылке. Пример параметра списка:

def test(a):
  a.append('new element')

a = ['first element']
test(a)

Результат в переменной "а": ['first element', 'new element']

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

Update: Кому интересно - загляните в комментарии, там тема расскрыта полностью.

Комментарии: 8

larin - 23.08.2010 Добрый день, Анатолий!
А чем такой способ не устраивает? По-моему, все четко и прозрачно: передаем список - получает ссылочное поведение, передаем кортеж - переменная не изменяется.

Если же передаете список и не хотите его изменять используйте модуль deepcopy
Толик Востряков - 23.08.2010 Такой способ вполне устраивает. Я просто допускаю мысль, что можно как-то по другому, поэтому и спрашиваю.
Михаил Едошин - 23.08.2010 Технически в Python любой параметр передается «по ссылке» — если посмотреть на исходники, там все функции, кроме нескольких, обмениваются между собой PyObject* — т. е. указателем на объект PyObject, или другой тип, производный от PyObject. Просто некоторые типы данных, как вы правильно пишете, неизменяемые, а другие изменяемые (immutable и mutable) — неизменяемые ведут себя как если бы передавались «по значению», а изменяемые — как «по ссылке». На самом же деле, например, мало того, что числа передаются тоже по ссылке, так они еще и используются повторно — любое число от -5 до 100 в Python — это один и тот же объект, что можно проверить оператором is или распечатать его командой repr() и посмотреть адрес.
nott - 23.08.2010 Вы сделали немного неправильный вывод (хотя с точки зрения пользователя ничего не меняется). Насколько я понимаю, в Python все передается по ссылке.

Изменяемые (mutable) типы отличаются лишь тем, что при помощи методов можно модифицировать их внутреннее состояние (при этом ссылка на объект не меняется).
Неизменяемые (immutable) типы точно также передаются по ссылке, просто у них нету методов, которые модифицируют внутренне состояние объекта. Поэтому невозможно сделать так, чтобы по старому адресу оказался другой объект.
wst - 23.08.2010
 В python ВСЕГДА параметр передается ссылка на объект, а не значение:


посмотрите, что будет в этом случае:

def test(a):
a = ['new element']

a = ['first element']
test(a)
print a


Возможно Вам нужен оператор global:
def test():
global a
a = ['new element']

a = ['first element']
test()


print a
werehuman - 23.08.2010

Возможно Вам нужен оператор global:


Глобальные переменные - зло. И это только в данном частном случае работать будет.

В питоне как в джаве - иммутабельны числа, булевы и строки. В общем, все типы, которым в C можно найти аналог (int, float, bool, ...) и char*.

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

Но если так уж хочется, то можно делать что-то в таком духе:

`In [1]: class ArgumentsClass: pass
...:

In [2]: def foo(args): args.x = "world"
...:

In [3]: abc = ArgumentsClass()

In [4]: abc.x = "hello"

In [5]: foo(abc) ; print abc.x
world`

Но это неудобный костыль.
Толик Востряков - 23.08.2010 Спасибо всем за комментарии! Тема расскрыта :)
Loststylus - 29.08.2010 Учите матчасть :))

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


Буду использовать, только для связи с тобой

Чтобы и другие могли узнать о тебе

Вы можете использовать markdown разметку.

Например:
**жирный**
*курсив*
## Заголовок

Не используйте html-тэги. Все ссылки станут активными, все переводы строк будут заменены на <br>
captcha