Мне нужно было передать в функцию параметр, в функции он изменяется и снаружи функции видно изменение. То есть фактически передать в функцию переменную по ссылке. Оказалось в Питоне с этим хитро. Есть изменяемые и неизменяемые переменные. Зависит от типа. Например, строки неизменяемый тип, а списки изменяемый. Соответственно строки передаются в функцию по значению, а список по ссылке. Пример параметра списка:
def test(a):
a.append('new element')
a = ['first element']
test(a)
Результат в переменной "а": ['first element', 'new element']
Если есть другие варианты явно указать, что параметр функции передается по ссылке, прошу в комментарии к посту.
Update: Кому интересно - загляните в комментарии, там тема расскрыта полностью.
| Толик Востряков - 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 |
посмотрите, что будет в этом случае: Возможно Вам нужен оператор global: def test(): global a a = ['new element'] print a |
| werehuman - 23.08.2010 |
Глобальные переменные - зло. И это только в данном частном случае работать будет. В питоне как в джаве - иммутабельны числа, булевы и строки. В общем, все типы, которым в 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 |
Учите матчасть :)) |
А чем такой способ не устраивает? По-моему, все четко и прозрачно: передаем список - получает ссылочное поведение, передаем кортеж - переменная не изменяется.
Если же передаете список и не хотите его изменять используйте модуль deepcopy