I read that thread, and am glad I did before asking like I was going
to, if only to avoid being yelled at for not understanding Python
variables
I understand them, I really do, and I know why they act the way they
do, but I still wanted a reference type for binding GUI objects to
data values - for example, a spinner control to an int value. In C++,
I do it by passing a pointer to an int to the control and letting it
do its thing. Theres no simple obvious way to do the same thing in
Python - I ended up by passing a namespace(any object) and an
attribute (by name) and then setting it via setattr in in the control,
which is non-obvious and icky.
ISTM that there are two main issues involved.
1) Can you code your intentions with some clean syntax?
1a) Is there clean syntax to help you think more fluently?
2) Is the implementation efficient enough for your use case?
(Ok, I couldn't help introducing 1a, because I think that is
where Python shines).
I think 2) can be ignored until we have a good proposal for 1) ;-)
IIUC what you want boils down to wanting to replace a value
via a reference object that you pass to a function, where the value
is known by name in some namespace, and you don't want
to use a (namespace, namestring) tuple as a reference object.
Actually, in general the value could be known by some access expression
that doesn't necessarily end in a name, like a[42]. Our magic ref expression
(let's use function syntax for now for creating the reference) becomes
more tricky. We now also have ref(a[42]) as well as ref(name).
For easy discussion of the concept, let's assume that refobj = ref(expr) works
for some subset of exprs and refobj lets us access the expr target via
refobj.value for assignment or in an expression. Note that the name 'value'
is not the name in ref(name), but is always 'value'. We can discuss later
whether we want syntactic sugar to spell refobj.value as @refobj or maybe
even plain refobj, but let's postpone that until we have agreed functionality
and some ideas on implementation.
So, to summarize, we have
refobj = ref(expr)
and we can assign to the indirect target and and use it in an expression
refobj.value = refobj.value + 1
with a fixed syntax that does not identify any of the original expression
(since "value" is an arbitrarily chosen mnemonic and attribute access is
an arbitrarily chosen accessor mechanism for discussion expediency).
For your example of ref(namespace.name) we could use my PNS class [1]
to get a refobj that acts as above, e.g.,
[1]
http://groups.google.com/group/comp.lang.python/msg/54a7ab01906683ca
But how would ref(a[42]) work? By analogy we might have a class PLE (pointer
to list element) and instantiate it by refobj = PLE(a, 42). That would be easy.
One could even imagine a multimethod __init__ for a PXX class that would handle
a number of common ref(expr) situations, if you pass the appropriate pieces of expr
as args. One could imagine automating this in various ways. E.g., treating ref
as a keyword and automatically detecting it in a module's AST and translating
the call to pick apart the passed expression suitably to make a call that
generates the refobj. But this is premature implementation ;-)
Let's get the requirements down first. One thing that pops up immediately
if you think about ref(namespace.name) vs ref(a[42]) is preservation of
the dynamic access semantics whose execution is deferred in time. I.e.,
a dangling pointer problem with additional twists.
If the essential ref infos are (namespace, name) and (a, 42), we must note that
we really implicitly made it
(namespace, ('__getattr__', '__setattr__', '__delattr__'), name)
and
(a, ('__getitem__', '__setitem__', '__delitem__'), 42)
(at least I did in the way I defined PNS, because deferred use of the refobj
to set a value implied doing getattr(namespace, name) at that time.
Accessor methods could also be bound at ref call time, with different semantics
resulting. I.e., we could have ref info stored as
((namespace.__getattr__, namespace.__setattr__, namespace.__delattr__), name)
and
((a.__getitem__, a.__setitem__, a.__delitem__), 42)
What is the real meaning desired for a refobj ? How should ref(42) be handled?
Should it become a legal refobj that only fails if used as assignment target,
so that it can be passed transparently to read-only users as well as references
to mutables that wind up only being used read-only?
Regards,
Bengt Richter