Хранение ссылки на ссылку в Python?

Используя Python, есть ли способ сохранить ссылку на ссылку, чтобы я мог изменить то, что эта ссылка ссылается в другом контексте? Например, предположим, что у меня есть следующий класс:

class Foo: def __init__(self): self.standalone = 3 self.lst = [4, 5, 6] 

Я хотел бы создать нечто похожее на следующее:

 class Reassigner: def __init__(self, target): self.target = target def reassign(self, value): # not sure what to do here, but reassigns the reference given by target to value 

Таким образом, следующий код

 f = Foo() rStandalone = Reassigner(f.standalone) # presumably this syntax might change rIndex = Reassigner(f.lst[1]) rStandalone.reassign(7) rIndex.reassign(9) 

Результатом будет f.standalone равный 7 и f.lst равный [4, 9, 6] .

По существу, это будет аналогом указателя на указатель.

Короче говоря, это невозможно. Вообще. Ближайший эквивалент хранит ссылку на объект, чей член / элемент, который вы хотите переназначить, плюс имя / индекс / ключ атрибута, а затем используйте setattr / setitem . Однако это дает совершенно другой синтаксис, и вы должны различать два:

 class AttributeReassigner: def __init__(self, obj, attr): # use your imagination def reassign(self, val): setattr(self.obj, self.attr, val) class ItemReassigner: def __init__(self, obj, key): # use your imagination def reassign(self, val): self.obj[self.key] = val f = Foo() rStandalone = AttributeReassigner(f, 'standalone') rIndex = ItemReassigner(f.lst, 1) rStandalone.reassign(7) rIndex.reassign(9) 

Я действительно использовал что-то очень похожее, но допустимых вариантов использования мало и далеко. Для членов глобалов / модулей вы можете использовать либо объект модуля, либо globals() , в зависимости от того, находитесь ли вы внутри модуля или вне его. Для местных переменных вообще нет эквивалента – результат locals() не может быть использован для надежного изменения локалей, это полезно только для проверки .

Я действительно использовал что-то очень похожее, но допустимых вариантов использования мало и далеко.

Простой ответ: вы не можете.
Сложный ответ: вы можете использовать лямбды. Вроде.

 class Reassigner: def __init__(self, target): self.reassign = target f = Foo() rIndex = Reassigner(lambda value: f.lst.__setitem__(1, value)) rStandalone = Reassigner(lambda value: setattr(f, 'strandalone', value)) rF = Reassigner(lambda value: locals().__setitem__('f', value) 

Если вам нужно отложить задание; вы можете использовать functools.partial (или просто lambda ):

 from functools import partial set_standalone = partial(setattr, f, "standalone") set_item = partial(f.lst.__setitem__, 1) set_standalone(7) set_item(9) 

Если reassign является единственной операцией; вам не нужен новый класс. Функции являются первоклассными гражданами в Python: вы можете назначить их переменной, сохранить в списке, передать в качестве аргументов и т. Д.

Это будет работать для содержимого объектов контейнера. Если вы не возражаете добавить один уровень косвенности в свои переменные (который вам понадобится в случае с указателем на указатель C), вы можете:

 class Container(object): def __init__(self, val): self.val = val class Foo(object): def __init__(self, target): self.standalone = Container(3) self.lst = [Container(4), Container(5), Container(6)] 

И вам совсем не нужен объект-ретранслятор.

 Class Reassigner(object): def __init__(self, target): self.target = target def reassign(self, value): self.target.val = value