Addressing the last element of a list

Antoon Pardon apardon at forel.vub.ac.be
Thu Nov 17 03:51:47 EST 2005


Op 2005-11-16, Mike Meyer schreef <mwm at mired.org>:
> Antoon Pardon <apardon at forel.vub.ac.be> writes:
>> Op 2005-11-15, Mike Meyer schreef <mwm at mired.org>:
>>> Antoon Pardon <apardon at forel.vub.ac.be> 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



More information about the Python-list mailing list