total idiot question: +=, .=, etc...

Tim Peters tim_one at email.msn.com
Sat Jun 26 19:48:15 CEST 1999


[Tim]
> ... any OO language with declarations has to allow local vars to
> shadow instance vars, else method implementations can be broken by
> trivial changes in far-removed superclasses

[Reimer Behrends]
> To the contrary; Eiffel, under no circumstances allows shadowing of
> instance variables by formal parameters or by local variables.

Let me ammend that, to "any OO language with declarations <that isn't
Eiffel> has to ..." <wink>.  Eiffel allows inherited features to be accessed
under local alias names as if the original name never existed (its "rename"
clauses), so it has *a* way to recover locally from trivial superclass name
changes.  Java (& most other languages) take a different approach.

> Yes, changing stuff in a superclass can thus break code in a subclass; but
> this can always happen (like if you add a new method that also exists in
> a subclass).  Doing a major internal change to a superclass requires at
> least rechecking subclasses, anyway.

I did say "trivial".  A purely local way of addressing this is vital:  the
subclass author may not be able to change the superclass code, or may not
even have read access to its source code; in the other direction, a
superclass author may have no idea who subclasses from them.

Eiffel and Java both "work" in this respect, albeit thanks to different
gimmicks.

> (And I prefer compilers that are too picky rather than too lenient.)

Excellent!  Me too.  So we're both strongly in favor of Python making you
explicitly identify your instance vars with a "self." prefix <wink>.

[Java shadowing]
> Can you point me to the place in the Java language specification where
> this is said?  I'm asking, because I've heard that, too, but haven't ever
> been able to find it and because the JDK happily allows to me shadow
> instance variables left and right.

I'm not sure what happened after the various forms of inner/nested classes
were introduced.  The full story in the original JLS is spread out all over
the place, most of which can be tracked down by following the index's
"hiding" entry.  Curiously, that *doesn't* point you to section 14.3.2,
which prohibits shadowing of locals by other locals or exception parameters.

It does generally allow shadowing of class and instance names, but sometimes
in the sense of allowing *potential* ambiguity provided that an ambiguous
name isn't actually referenced.

In the latter cases, Eiffel requires local renaming of ambiguous inherited
names, while Java requires explicit qualification.  You can probably guess
which I generally prefer <wink>.

>> Readability is more important to me over the long haul.

> Huh? Where have I said otherwise? I just happen to think that these two
> goals are not mutually exclusive. And there should be a better solution
> than the language ordaining a strange kind of Hungarian notation.

The C++ conventions I mentioned were a strange kind of Hungarian; "x.y" is
just the way Python *always* spells "give me the value of attribute y in x's
namespace", whether x is a module, class or instance object.  Consistent,
explicit & obvious, given Python's modeling of modules, classes and
instances *as* namespaces.

>> Say what you like, but which vars belong to the instance is screamingly
>> obvious the instant you see
>>
>>     self.x = self.y + k
>>
>> while in
>>
>>     x = y + k
>>
>> it's at best a minor puzzle and at worst a long & tedious grep project.

> I tell you what--I have this great idea for an addition to Python. You
> know that you often can't tell what type a variable is? Well, we could
> introduce the following convention:
>
> 	Require variables to be prefixed with "$" to denote scalar
> 	values--strings and integers, "@" for lists, and "%" for
> 	dictionaries.
>
> Given the precedent of having to use self to access instance variables,
> this is entirely consistent with the current language, and is going to
> eliminate all those nasty problems where you can't tell from the context
> what the type of a variable or function is. :)
>
> 	Tongue-firmly-in-cheek-ly yours, Reimer

Seriously, languages rarely start out doing things that are insane within
their own worldview.  Perl would be *much* harder to work with in the
absence of those $@%& thingies!  Array vs scalar is an ubiquitous magical
distinction in Perl that affects semantics in crucial ways, and without the
$@ decorations you'd be left with no way to determine the intent of a line;
e.g.,

    x = split;

That does wildly different things depending on whether x is a scalar or an
array, so "$x" vs "@x" is a crucial clue.  Python doesn't have that kind of
context sensitivity, and doesn't build up complex data structures out of
explicit chains of scalar references either (and again you need the $%@
thingies to dope out what a chain of Perl *dereferences* is doing).

So the decorations solve a problem in Perl that Python doesn't have, so they
make good sense in Perl but not in Python.  Python's object.attr notation
solves Python's problem:  with respect to which namespace is attr to be
resolved?  Christian Tismer once suggested that Python take that another
step, and require that e.g.

    def f(x, y):
        global sum1, sum2, total
        sum1 = x
        sum2 = y
        total = x + y

instead be written

    def f(x, y):
        global.sum1 = x
        global.sum2 = y
        global.total = x + y

I think that's a fine idea too.  I'd even go a step toward Perl and make
mapping objects use "{}" for indexing instead of "[]".  Stop me before I sin
<wink>.

not-eager-to-trade-instant-certainty-for-potential-confusion-unless-
    the-confusion-is-helpful-ly y'rs  - tim






More information about the Python-list mailing list