Label-Value (was: Re: Inheriting the @ sign from Ruby)

Alex Martelli aleaxit at yahoo.com
Wed Dec 13 13:27:28 CET 2000


"Aahz Maruch" <aahz at panix.com> wrote in message
news:9165he$lon$1 at panix3.panix.com...
> In article <r0pwvd51gga.fsf at black.cs.washington.edu>,
> Daniel Wood  <daniel at cs.washington.edu> wrote:
> >
> >I'm talking about an *object* that is both an int and mutable.
> >
> >class MutableInt:
> > def __init__( self, default ):
> > self.value = default
> > def set( self, val ):
> > self.value = val
> > def get( self ):
> > return self.value
> > # And maybe
> > def __int__( self ):
> > return self.value
> >
> >My question is: am I confused if I think that this might be useful?
> >And if it is useful then what's the most pythonic way to do this.
> >(And if the best thing is a list of one element, why isn't that much
> >more "hack" than "idiom"?)
>
> This is useful and you've just used the most Pythonic mechanism.

Actually, removing the 'maybe' __int__, one gets full generality
and simplicity -- no specific-type-being-held implications.  One
useful variation:

class Mutable:
    def __init__(self, default=None):
        self.value = default
    def set(self, value):
        self.value = value
        return value
    def get(self):
        return self.value


The 'return value' at the end of the set method is intended to
make this the answer to the perennial 'why isn't assignment an
expression in Python and what can I do about it', by the way:

    line = Mutable()

    while line.set(myfile.readline()):
        frobozz(line.get())

or even:

    temp = Mutable()
    if temp.set(complicated(stuff)) > threshold:
        elaborate_processing(temp.get())

as an alternative to the more normal:

    temp = complicated(stuff)
    if temp > threshold:
        elaborate_processing(temp)


No doubt class Mutable might be 'usefully' (?) enhanced by all
sorts of delegations to self.value.  Here, for example, is
a version that is rather 'transparent' with respect to a
lot of operations:

class TransparentMutable:
    def __init__(self, default=None):
        self.__value = default
    def set(self, value):
        self.__value = value
        return value
    def get(self):
        return self.__value
    def __coerce__(self,other):
        return coerce(self.__value,other)
    def __str__(self):
        return str(self.__value)
    def __repr__(self):
        return repr(self.__value)
    def __getattr__(self, name):
        return getattr(self.__value, name)
    def __setattr__(self, name, value):
        if name=='_Mutable__value':
            self.__dict__[name]=value
        else: return setattr(self.__value, name, value)
    def __getitem__(self, index):
        return self.__value[index]
    def __setitem__(self, index, value):
        self.__value[index] = value


For many uses, an instance of TransparentMutable will now be
almost interchangeable with whatever its __value is holding
at this time...:

>>> m=TransparentMutable()
>>> m.set("loopy")
'loopy'
>>> m+'plop'
'loopyplop'
>>> 'plop'+m
'ploploopy'
>>> for x in m:
...     print x
...
l
o
o
p
y
>>> m.set(3.1415926)
3.1415926000000001
>>> (4.0/3)*m*(1.1*1.1*1.1)
5.5752796674666678
>>>

note that we don't need to define the various operators, as
__coerce__ comes in handy here -- unless we try to operate
on TWO 'transparent mutables', which rather spoils things:-).


Is it worth pursuing this 'rich', aka 'transparent',
approach?  I don't think it is.  The simple Mutable class,
which makes no attempt whatsoever to pass itself off as
something it isn't, has potentially high value for its
simplicity -- and the need to explicitly call .get to
obtain the value it's currently wrapping is no bad thing,
either (explicit is better than implicit...!).

'TransparentMutable' has only one hypothetical advantage:
you can try to tweak it enough to be able to 'drop' it
into existing code without reworking that code -- maybe.
And then again, maybe there could be some little anomaly
here or there (multiplying two TransparentMutable's rather
than one of those and one true number, for example) which
might cause trouble.

I think refactoring the 'existing code' (perhaps using
the simple Mutable) is going to yield better returns than
hacking on TransparentMutable or any equivalent thereof.

Remember Firmitas, Utilitas, Venustas?  Well, Venustas,
beauty, is in the eye of the beholder.  Mutable, the simple
kind, has excellent Firmitas, solidity -- it's simple enough
that it obviously has no defects.  It does the single small
job it's designed to do: letting you 'set this value aside
for later use' as a part of an expression, and get the value
back again; explicitly for each half of the job; period.

The defect of TransparentMutable (and other hacks to that
effect) is that it tries to put Utilitas, convenience, AHEAD
of Firmitas; it strives so hard to be 'convenient to use',
that it becomes somewhat complicated, and therefore fragile.

Listing "comodità" before "perpetuità", as I argued in a
post yesterday on a different thread ('convenience' before
'solidity'; Utilitas before Firmitas), was an ideological
aberration (originally by L.B.Alberti, later by Palladio)
wrt Vitruvius' original formulation.  They didn't really
practice what they preached, IMHO: the Tempio Malatestiano
or the Villa Foscari do not in the least compromise
structural solidity in the quest for convenience or beauty.

Maybe they took solidity _for granted_, because, in their
(Renaissance) times and in their (Architecture) calling,
compromises regarding solidity were simply unthinkable.
Well, we're not so lucky, in the software field, today; the
Firmitas of *by far* most software around is imperfect.

We *must* live by "do the simplest thing that can possibly
work" -- give solidity its proper, foremost place.  One
of the debilitating factor for much current software is
a misplaced emphasis on assumed 'convenience' (funky GUIs,
quirky shortcuts, special cases aplenty) to the detriment
of solidity.  A small but crucial step to reverse this
trend, is to start by putting the order right once more...
the way Vitruvius had it!-)


Alex






More information about the Python-list mailing list