I want form.data['field']
and
form.field.value
to always have the
same value
This is feasible, because it involves decorated names and indexing -- i.e., completely different constructs from the barenames a
and b
that you're asking about, and for with your request is utterly impossible. Why ask for something impossible and totally different from the (possible) thing you actually want?!
Maybe you don't realize how drastically different barenames and decorated names are. When you refer to a barename a
, you're getting exactly the object a
was last bound to in this scope (or an exception if it wasn't bound in this scope) -- this is such a deep and fundamental aspect of Python that it can't possibly be subverted. When you refer to a decorated name x.y
, you're asking an object (the object x
refers to) to please supply "the y
attribute" -- and in response to that request, the object can perform totally arbitrary computations (and indexing is quite similar: it also allows arbitrary computations to be performed in response).
Now, your "actual desiderata" example is mysterious because in each case two levels of indexing or attribute-getting are involved, so the subtlety you crave could be introduced in many ways. What other attributes is form.field
suppose to have, for example, besides value
? Without that further .value
computations, possibilities would include:
class Form(object):
...
def __getattr__(self, name):
return self.data[name]
and
class Form(object):
...
@property
def data(self):
return self.__dict__
The presence of .value
suggests picking the first form, plus a kind-of-useless wrapper:
class KouWrap(object):
def __init__(self, value):
self.value = value
class Form(object):
...
def __getattr__(self, name):
return KouWrap(self.data[name])
If assignments such form.field.value = 23
is also supposed to set the entry in form.data
, then the wrapper must become more complex indeed, and not all that useless:
class MciWrap(object):
def __init__(self, data, k):
self._data = data
self._k = k
@property
def value(self):
return self._data[self._k]
@value.setter
def value(self, v)
self._data[self._k] = v
class Form(object):
...
def __getattr__(self, name):
return MciWrap(self.data, name)
The latter example is roughly as close as it gets, in Python, to the sense of "a pointer" as you seem to want -- but it's crucial to understand that such subtleties can ever only work with indexing and/or decorated names, never with barenames as you originally asked!