Элегантный способ изменить список переменных по ссылке в Python? - PullRequest
4 голосов
/ 26 января 2011

Допустим, у меня есть функция f (), которая берет список и возвращает мутацию этого списка.Если я хочу применить эту функцию к пяти переменным-членам в моем экземпляре класса (i), я могу сделать это:

for x in [i.a, i.b, i.c, i.d, i.e]:
    x[:] = f(x)

1) Есть ли более элегантный способ?Я не хочу, чтобы f () модифицировал переданный список.

2) Если мои переменные содержат простое целое число (которое не будет работать с нотацией слайса), есть ли способ?(f () также будет принимать и возвращать целое число в этом случае)

Ответы [ 3 ]

4 голосов
/ 26 января 2011

Другое решение, хотя оно, вероятно, не изящно:

for x in ['a', 'b', 'c', 'd', 'e']:
    setattr(i, x, f(getattr(i, x)))
2 голосов
/ 26 января 2011

В конечном счете, то, что вы хотите сделать, несовместимо с тем, как структурирован Python.У вас есть самый элегантный способ сделать это уже в том случае, если ваши переменные являются списками, но это невозможно с числами.

Это потому, что переменных не существует в Python. Ссылки сделать.Таким образом, i.x - это не список, это ссылка на список .Аналогично, если он ссылается на число.Так что если i.x ссылается на y, то i.x = z на самом деле не меняет значение y, оно меняет расположение в памяти, на которое указывает i.x.

В большинстве случаев переменные рассматриваются как блоки, содержащие значение.Имя на коробке.В python значения являются фундаментальными, а «переменные» - это просто теги, которые привязываются к определенному значению.Очень приятно, когда вы к этому привыкнете.

В случае со списком вы можете использовать назначение срезов, как вы уже это делаете.Это позволит всем ссылкам на список видеть изменения, потому что вы изменяете сам объект списка.В случае числа это сделать невозможно, поскольку числа в Python являются неизменяемыми объектами.Это имеет смысл.Пять - это пять, и вы мало что можете сделать, чтобы изменить это.Если вы знаете или можете определить имя атрибута, то вы можете использовать setattr для его изменения, но это не изменит других ссылок , которые могут уже существовать.

Как говорит Рэйф Кеттлер, если вы можете быть более точным в отношении того, что вы на самом деле хотите сделать, то мы можем придумать простой элегантный способ сделать это.

2 голосов
/ 26 января 2011

Python не имеет передачи по ссылке. Лучшее, что вы можете сделать, это написать функцию, которая создает новый список, и назначить результат функции исходному списку. Пример:

def double_list(x):
    return [item * 2 for item in x]

nums = [1, 2, 3, 4]
nums = double_list(nums) # now [2, 4, 6, 8]

Или еще лучше:

nums = map(lambda x: x * 2, nums)

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

Возможно, вы сможете взломать решение, но лучше всего сделать это обычным способом.

EDIT

Мне приходит в голову, что я на самом деле не знаю, что вы пытаетесь делать, в частности. Возможно, если бы вы разъяснили вашу конкретную задачу, мы могли бы найти решение, которое позволит Python?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...