Ich habe die folgende einfache Klasse geschrieben, um einen Zeiger in Python effektiv zu emulieren:
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)
Hier ist ein Anwendungsbeispiel (von einer Jupyter-Notizbuchseite):
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]
Natürlich ist es auch einfach, diese Funktion für diktierte Elemente oder Attribute eines Objekts zu verwenden. Es gibt sogar eine Möglichkeit, mit globals () das zu tun, wonach das OP gefragt hat:
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)
Dies druckt 2 aus, gefolgt von 3.
Auf diese Weise mit dem globalen Namespace zu spielen, ist eine schreckliche Idee, aber es zeigt, dass es möglich ist (wenn nicht ratsam), das zu tun, was das OP verlangt.
Das Beispiel ist natürlich ziemlich sinnlos. Ich habe jedoch festgestellt, dass diese Klasse in der Anwendung, für die ich sie entwickelt habe, nützlich ist: ein mathematisches Modell, dessen Verhalten von zahlreichen vom Benutzer einstellbaren mathematischen Parametern verschiedener Typen bestimmt wird (die, da sie von Befehlszeilenargumenten abhängen, nicht bekannt sind zur Kompilierungszeit). Und sobald der Zugriff auf etwas in einem Parameter-Objekt gekapselt wurde, können alle diese Objekte auf einheitliche Weise bearbeitet werden.
Obwohl es nicht viel wie ein C- oder C ++ - Zeiger aussieht, löst dies ein Problem, das ich mit Zeigern gelöst hätte, wenn ich in C ++ geschrieben hätte.