Op 2005-11-16, Mike Meyer schreef <[EMAIL PROTECTED]>: > Antoon Pardon <[EMAIL PROTECTED]> writes: >> Op 2005-11-15, Mike Meyer schreef <[EMAIL PROTECTED]>: >>> Antoon Pardon <[EMAIL PROTECTED]> writes: >>>>>> Like having an assignment operator (let use @= for it) next to a >>>>>> (re)bind operator. >>>>>> We could then have something like the following. >>>>>> a = 5 >>>>>> b = a >>>>>> a @= 7 >>>>>> b ==> would result in 7. >>>>> You've just overwritten the object referred to by the token "5" in the >>>>> source code with the value 7, so you get: >>>>> print 5 >>>>> 7 >>>> You have a valid point, but I think a different approach is possible. >>>> Don't make the distinction between mutable and immutable types but >>>> between mutable and immutable objects. So an int wouldn't be an >>>> immutable type, but 5 would be an immutable object. >>>> So the code above I gave would throw an exception, but the following >>>> might work. >>>> a @= 5 >>>> b = a >>>> b @= 7 >>>> a ==> would result in 7. >>> >>> Which solves that issue but brings up - well, more issues. What >>> happens if the third line is 'b @= "seven"'? Does this require an >>> extra level of indirection in the implementation? Avoiding that kind >>> of thing was the reason for suggesting this: >> >> It depends on how far you want to go. >> >> I think one can argue that in case of an inplace replacement, this >> only makes sense if the two objects belong to the same class. So >> no extra level of indirection is then required. > > Now factor in inheritance. Do users of this facility have to worry > about static OO typing? That is, two objects that are otherwise > completely interchangeable will raise an exception if you try to > assign one to a variable holding the other, because they have the > wrong type. That seems unpythonic.
I don't care much about pythonic or not. It seems a very volatile concept, that adapts as the language evolves. I wouldn't be surprised if augmented arithmetic operations would have been considered unpythonic at some point. You could see this limitation as a wart, but IMO the idea would still be usefull with that limitation. The limitation would ensure for example that although the value of an argument could change, it's class couldn't. I think that is worthwhile. >> Otherwise it really depends on how the builtin objects are implemented. >> For user classes, a somewhat simplistic implementation could be >> something like: >> >> def '@=' (one, two): >> one.__dict__.clear() >> one.__dict__.update(two.__dict__) > > Wouldn't one.__dict__ = dict(**two.__dict__) be a bit better? > > Anyway, this won't' work if the class of one of the objects has > slots. So? I wrote it was a simplistic idea. but things like setattr and getattr, still work with objects that have slots. So which attributes are present for a particulare object has to be available in the python interpreter. So my guess is that slots wont be the big stumbling block, should one consider implementing something like this. >>> The critical thing is that this doesn't introduce any new facilities >>> into the language, just some new syntax, so there's no implementation >>> impact. In fact, if you're willing to put up with some notational >>> abuse, we can do this now: >>> >>> class Ref(object): >>> _unbound = object() >>> def __new__(cls, value = _unbound): >>> """We're an object, but need to ignore the optional argument.""" >>> >>> return object.__new__(cls) >>> >>> def __init__(self, value = _unbound): >>> """Bind the optional value, if provided.""" >>> if value is not self._unbound: >>> self._value = value >>> >>> def __pos__(self): >>> """Return value, if bound.""" >>> try: >>> return self._value >>> except AttributeError: >>> raise ValueError, "%s object does not have a value stored." % \ >>> self.__class__.__name__ >>> >>> def __iadd__(self, value): >>> self._value = value >>> return self >>> >>> Usage: >>> >>>>>> x = Ref.Ref() >>>>>> x += 23 >>>>>> +x >>> 23 >>>>>> a = x >>>>>> x += 25 >>>>>> +a >>> 25 >>>>>> a += "this is a test" >>>>>> +x >>> 'this is a test' >>> >>> Since it doesn't have real lannguage support, things like +x += 25 >>> don't work. That's the only obvious gotcha. Maybe ~ would be a better >>> prefix. >> >> I'm a bit puzzled on how you would implement this as real language >> support. As far as I understand this only works with Ref objects. > > Correct. That's the point. > >> You can't do something like the following. >> >> l = [3, 7] >> a = Ref(l[0]) >> >> Instead you would have to do something like >> l = [Ref(3), Ref(7)] >> a = l[0] >> >> So it seems that if you want to use this idea for implementing langauge >> support you will have to wrap all objects in a Ref internally and this >> seems some kind of extra indirection too. > > No, the idea is to expose this class to the user. They would have to > explicitly wrap objects that they want to be able to be get a > reference to. Well that seems less usefull to me. Let me explain, what I would like it for. Sometime I'm programming with tree like structures. Occasionaly such a tree has to be restructured. Now of course I could write it like this: def restruct(tr): if ...: tr.left = restruct(tr.left) tr.right = restruct(tr.right) tmp = tr.left tr.left = tmp.right tmp.right = tr return tmp. ... tree = restruct(tree) But this feels wrong to me. It gives the impression that the following would give you a new restructured tree while the old one is still available, which isn't so: newtree = restruct(tree) IMO being able to write: restruct(tree) With as a result that tree would now be the new root of the restructered tree, would better convey what is going on. Now having to make my tree object into a ref, which would mean all nodes in the tree, seems overkill. Maybe we can consider in-out parameters in python? It is not as powerfull as reference variables or in place replacements but from what I have seen here in the newsgroup would be sufficient for most users that ask for something like this. -- Antoon Pardon -- http://mail.python.org/mailman/listinfo/python-list