Создать ссылку на переменную (похожую на PHP «= &»)?

В PHP можно создать ссылочную переменную, так что две именованные переменные могут выглядеть одинаково:

$a = 1; $b =& $a; echo $a; // 1 echo $b; // 1 $b = 2; echo $a; // 2 

Я ищу для достижения чего-то подобного в Python. В частности, я хочу создать ссылку на свойство объекта, например:

 class Foo(object): @property def bar(self): return some_calculated_value foo_instance = Foo() ref = foo_instance.bar # so that 'ref' is referencing the bar property on foo, calculated when used. 

Это возможно?

Есть еще несколько магии, которые можно сделать в Python (не то, что я бы рекомендовал, и вам потребуется копать с вашей стороны ;-), но использование закрытия может быть достаточно для ваших нужд:

 get_x = lambda: foo_instance.bar get_x() # yahoo! 

Изменить, для тех, кто хочет «поддержки обновления», все дело в закрытии:

 def wrap_prop (obj, pname): def _access(*v): if not len(v): return getattr(obj, pname) else setattr(obj, pname, v[0]) return _access class z (object): pass access = wrap_prop(z(), "bar") access(20) access() # yahoo! \o/ 

Не выйдя за пределы обычно (для меня :-), принятого Python, это также можно было бы записать для возврата объекта с пересылкой / прокси-ресурсом, представьте себе:

 access = wrap_prop(z(), "bar") access.val = 20 access.val # yahoo \o/ 

Некоторые интересные ссылки:

Нет, вы не хотите. Все имена в Python являются ссылками, но они всегда ссылаются на объекты , а не на ссылки на переменные . У вас не может быть локального имени, которое, когда «используется», переоценивает то, что оно создало.

То, что вы можете иметь, – это объект, который действует как прокси-сервер, делегируя большинство операций над ним на операции над тем, что он ссылается внутренне. Однако это не всегда прозрачно, и есть некоторые операции, которые вы не можете прокси. Также часто бывает неудобно иметь то, что вы проксируете для изменения во время операции. В общем, обычно лучше не пытаться это делать.

Вместо этого в вашем конкретном случае вы будете держать foo_instance вместо ref и просто использовать foo_instance.bar всякий раз, когда хотите «использовать» ссылку ref . Для более сложных ситуаций или для большей абстракции вы можете иметь отдельный тип с свойством, который сделал именно то, что вы хотели, или функцией (как правило, закрытием), которая знала, что можно получить и где.

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

 class PropertyRef: def __init__(self, obj, prop_name): klass = obj.__class__ prop = getattr(klass, prop_name) if not hasattr(prop, 'fget'): raise TypeError('%s is not a property of %r' % (prop_name, klass)) self.get = lambda: prop.fget(obj) if getattr(prop, 'fset'): self.set = lambda value: prop.fset(obj, value)) class Foo(object): @property def bar(self): return some_calculated_value >>> foo_instance = Foo() >>> ref = PropertyRef(foo_instance, 'bar') >>> ref.get() # Returns some_calculated_value >>> ref.set(some_other_value) >>> ref.get() # Returns some_other_value 

BTW, в примере, который вы указали, свойство доступно только для чтения (не имеет сеттера), поэтому вы все равно не сможете его установить.

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