Я написал следующий простой класс для эффективной эмуляции указателя в python:
class Parameter:
"""Syntactic sugar for getter/setter pair
Usage:
p = Parameter(getter, setter)
Set parameter value:
p(value)
p.val = value
p.set(value)
Retrieve parameter value:
p()
p.val
p.get()
"""
def __init__(self, getter, setter):
"""Create parameter
Required positional parameters:
getter: called with no arguments, retrieves the parameter value.
setter: called with value, sets the parameter.
"""
self._get = getter
self._set = setter
def __call__(self, val=None):
if val is not None:
self._set(val)
return self._get()
def get(self):
return self._get()
def set(self, val):
self._set(val)
@property
def val(self):
return self._get()
@val.setter
def val(self, val):
self._set(val)
Вот пример использования (со страницы тетради Jupyter):
l1 = list(range(10))
def l1_5_getter(lst=l1, number=5):
return lst[number]
def l1_5_setter(val, lst=l1, number=5):
lst[number] = val
[
l1_5_getter(),
l1_5_setter(12),
l1,
l1_5_getter()
]
Out = [5, None, [0, 1, 2, 3, 4, 12, 6, 7, 8, 9], 12]
p = Parameter(l1_5_getter, l1_5_setter)
print([
p(),
p.get(),
p.val,
p(13),
p(),
p.set(14),
p.get()
])
p.val = 15
print(p.val, l1)
[12, 12, 12, 13, 13, None, 14]
15 [0, 1, 2, 3, 4, 15, 6, 7, 8, 9]
Конечно, также легко сделать эту работу для надиктованных предметов или атрибутов объекта. Есть даже способ сделать то, что просил OP, используя globals ():
def setter(val, dict=globals(), key='a'):
dict[key] = val
def getter(dict=globals(), key='a'):
return dict[key]
pa = Parameter(getter, setter)
pa(2)
print(a)
pa(3)
print(a)
Это напечатает 2, а затем 3.
Подобное взаимодействие с глобальным пространством имен - это явно ужасная идея, но она показывает, что можно (если не желательно) делать то, о чем просил ФП.
Пример, конечно, довольно бессмысленный. Но я обнаружил, что этот класс полезен в приложении, для которого я его разработал: математическая модель, поведение которой определяется многочисленными настраиваемыми пользователем математическими параметрами различных типов (которые, поскольку они зависят от аргументов командной строки, неизвестны во время компиляции). И как только доступ к чему-либо был инкапсулирован в объекте Parameter, всеми такими объектами можно манипулировать единообразным образом.
Хотя это не очень похоже на указатель C или C ++, это решает проблему, которую я бы решил с помощью указателей, если бы писал на C ++.