J'ai écrit la classe simple suivante comme, en fait, un moyen d'émuler un pointeur en 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)
Voici un exemple d'utilisation (à partir d'une page de notebook 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]
Bien sûr, il est également facile de faire ce travail pour les éléments dict ou les attributs d'un objet. Il existe même un moyen de faire ce que l'OP a demandé, en utilisant 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)
Cela imprimera 2, suivi de 3.
Jouer avec l'espace de noms global de cette manière est une sorte de transparence une idée terrible, mais cela montre qu'il est possible (si cela n'est pas conseillé) de faire ce que l'OP a demandé.
L'exemple est, bien entendu, assez inutile. Mais j'ai trouvé cette classe utile dans l'application pour laquelle je l'ai développée: un modèle mathématique dont le comportement est régi par de nombreux paramètres mathématiques réglables par l'utilisateur, de types divers (qui, parce qu'ils dépendent d'arguments de ligne de commande, ne sont pas connus au moment de la compilation). Et une fois que l'accès à quelque chose a été encapsulé dans un objet Parameter, tous ces objets peuvent être manipulés de manière uniforme.
Bien que cela ne ressemble pas beaucoup à un pointeur C ou C ++, cela résout un problème que j'aurais résolu avec des pointeurs si j'écrivais en C ++.