Addressing the last element of a list

Mike Meyer mwm at mired.org
Wed Nov 16 14:10:22 EST 2005


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.

> 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.

>> 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. Other object types can be implemented without having to
worry about assigning to them. If you want to assign to an object, you
cdreate it as a Ref. You still have to have a special syntax so you
can distinguish assigning to a Ref from binding a name, and getting
the value of the Ref vs. getting the Ref.

    <mike
-- 
Mike Meyer <mwm at mired.org>			http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.



More information about the Python-list mailing list