Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

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

2 views
Skip to first unread message

Preston Landers

unread,
Jun 22, 1999, 3:00:00 AM6/22/99
to
Hi there,

another question in this popular series of foolish questions...

Can someone *please* give me a good reason why Python doesn't yet have
+=, -=, and .= and other such operators? I know it's just syntactic
sugar, but damn, it is such sweet sugar!

Also, if this is in 1.5.2+, please forgive me, as I'm not up to speed
on the new versions yet. And I have searched the FAQ for this
question but have not found it.

many thanks,

---Preston

Zigron

unread,
Jun 22, 1999, 3:00:00 AM6/22/99
to

Reimer Behrends <behr...@cse.msu.edu> wrote in message
news:slrn7n0rr2....@allegro.cse.msu.edu...
> Preston Landers (plan...@mail.utexas.edu) wrote:
> Personally, I can easily live without a construct that I can use on
> average once every three screens of code or so. On the other hand, I
> _am_ getting pretty sick of having to type self.whatever countless
> times, where pretty much any other language allows me to discard the
> "self." part. Not only is it annoying to type, it also reduces the
> readability of OO code a lot, much like the gratuitious use of
> punctuation characters as variable prefixes in Perl does.
>
> Among all the suggestions for Python 2.0, removing the necessity of
> prefixing methods and instance variables with "self." (and not having
> to list it as an argument, either) would be my #1 wish.

Whyfor? I personally like the seperate scopes, beween the class
and the method. It makes it so I don't have to clean up as much. I can
use as many temporary variables as I want in a method, and as soon
as that method is gone...... its gone.
The self.attribute thing makes sense. Each object has its own scope,
er, namespace, whatever. Methods are considered objects, as are
classes. Removing the 'self' requirement would, to me, change that.
Methods wouldn't be objects anymore. :) At least it seems so to me,
.. they'd be almost-objects, maybe. I thought pv2 was going to
objectify eeeeverything. (I can't tell you how much I want strings
turned into objects! "blah".append('hi') should return 'blahhi'! :-))

I think that would have further reprocussions, maybe,..maybe not,
dunno. I'm just a newbie.

--Stephen


Bernhard Reiter

unread,
Jun 23, 1999, 3:00:00 AM6/23/99
to
On 22 Jun 1999 21:54:42 -0500, Preston Landers <plan...@mail.utexas.edu> wrote:
>Can someone *please* give me a good reason why Python doesn't yet have
>+=, -=, and .= and other such operators? I know it's just syntactic
>sugar, but damn, it is such sweet sugar!

From what I understand, the python creators consider it unnecessary
syntactic sugar. In fact they want one good way of writing expressions.
The lack of these operators makes the source code more readable.

+= just saves some space and typing time.
Your editor (given it is powerful enough can easily) immitate
that piece of sugar for your and make it personal syntactic honey!

Here is my posted vim example:
|>> For vim, the following does the trick (without the special word matching
|>> caps new vim versions provide. the ":noh is for people using hlsearch in
|>> vim 5.x version.)
|
|:map! += ^[:s/\([a-zA-Z_][a-zA-Z0-9_]*\)$/\1=\1+/^M:noh^MA
|
|Where ":" means go into vim Commandmode
| "^[" means Esc, you have to enter it pressing Ctrl-v and then Esc
| "^M" means "Return', you have to enter pressing Ctrl-v and then Return


>Also, if this is in 1.5.2+, please forgive me, as I'm not up to speed
>on the new versions yet.

It's not in there, I guess.

Bernhard

--
Research Assistant, Geog Dept UM-Milwaukee, USA. (www.uwm.edu/~bernhard)
Funding/Promoting Association for a Free Informational Infrastructure (ffii.org)

Reimer Behrends

unread,
Jun 23, 1999, 3:00:00 AM6/23/99
to
Preston Landers (plan...@mail.utexas.edu) wrote:
> Can someone *please* give me a good reason why Python doesn't yet have
> +=, -=, and .= and other such operators? I know it's just syntactic
> sugar, but damn, it is such sweet sugar!

Few people, I think, have ever tried to objectively count how often such
a construct is used. The Python 1.5.2 source, for instance, has
approximately one of ++, --, +=, -=, *=, /= every 40 lines. If you do
not count the occurrences if ++ and -- in for loops, for which there's a
construct in Python anyway, you can roughly double that number. Now, C
is not Python, but it's a good first-order approximation of how often
you need it--the Python source is one of the cleanest C programs I know
of.

Personally, I can easily live without a construct that I can use on
average once every three screens of code or so. On the other hand, I
_am_ getting pretty sick of having to type self.whatever countless
times, where pretty much any other language allows me to discard the
"self." part. Not only is it annoying to type, it also reduces the
readability of OO code a lot, much like the gratuitious use of
punctuation characters as variable prefixes in Perl does.

Among all the suggestions for Python 2.0, removing the necessity of
prefixing methods and instance variables with "self." (and not having
to list it as an argument, either) would be my #1 wish.

[...]

Reimer Behrends

Michael Hudson

unread,
Jun 23, 1999, 3:00:00 AM6/23/99
to
behr...@cse.msu.edu (Reimer Behrends) writes:

> Preston Landers (plan...@mail.utexas.edu) wrote:
> > Can someone *please* give me a good reason why Python doesn't yet have
> > +=, -=, and .= and other such operators? I know it's just syntactic
> > sugar, but damn, it is such sweet sugar!
>
> Few people, I think, have ever tried to objectively count how often such
> a construct is used. The Python 1.5.2 source, for instance, has
> approximately one of ++, --, +=, -=, *=, /= every 40 lines. If you do
> not count the occurrences if ++ and -- in for loops, for which there's a
> construct in Python anyway, you can roughly double that number. Now, C
> is not Python, but it's a good first-order approximation of how often
> you need it--the Python source is one of the cleanest C programs I know
> of.
>
> Personally, I can easily live without a construct that I can use on
> average once every three screens of code or so. On the other hand, I
> _am_ getting pretty sick of having to type self.whatever countless
> times, where pretty much any other language allows me to discard the
> "self." part. Not only is it annoying to type, it also reduces the
> readability of OO code a lot, much like the gratuitious use of
> punctuation characters as variable prefixes in Perl does.

I sometimes think this when writing Python; but in my summer job which
I've just started, I'm frequently faced with large screenfulls of C++
and not being able to tell whether a given variable is local, static,
class or global at a glance is mightily annoying.

Just my humble opinion.
Michael

cat...@my-deja.com

unread,
Jun 23, 1999, 3:00:00 AM6/23/99
to

> |>> vim 5.x version.)
> |
> |:map! += ^[:s/\([a-zA-Z_][a-zA-Z0-9_]*\)$/\1=\1+/^M:noh^MA
> |
> |Where ":" means go into vim Commandmode
> | "^[" means Esc, you have to enter it pressing Ctrl-v and
then Esc
> | "^M" means "Return', you have to enter pressing Ctrl-v and
then Return

I've got the following in my .vimrc file:
au BufReadPost * if b:current_syntax == "python"
au BufReadPost * map! += ^[:s/\(\S*\)$/\1=\1+/^M:noh^MA
au BufReadPost * endif

What this does is check to see if the current syntax is python. The
mapping hopefully covers more complex
expressions than yours does, it takes all the previous non-whitespace
characters as the expression to copy. I wonder if there's a way to use
the vim syntax parsing mechanism to determine what an expression is?

Cheers,
Chris


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.

Neel Krishnaswami

unread,
Jun 23, 1999, 3:00:00 AM6/23/99
to
In article <m3aetr2...@atrus.jesus.cam.ac.uk>,
Michael Hudson <mw...@cam.ac.uk> wrote:

>behr...@cse.msu.edu (Reimer Behrends) writes:
>
>> Personally, I can easily live without a construct that I can use on
>> average once every three screens of code or so. On the other hand, I
>> _am_ getting pretty sick of having to type self.whatever countless
>> times, where pretty much any other language allows me to discard the
>> "self." part. Not only is it annoying to type, it also reduces the
>> readability of OO code a lot, much like the gratuitious use of
>> punctuation characters as variable prefixes in Perl does.
>
>I sometimes think this when writing Python; but in my summer job which
>I've just started, I'm frequently faced with large screenfulls of C++
>and not being able to tell whether a given variable is local, static,
>class or global at a glance is mightily annoying.

I don't mind writing self.foo = bar, for the reason you describe, but
I know I hate having to write self.__class__.member = foo in order to
keep inheritance from breaking:

class Foo:
x = 9
def munge_x(self, x):
Foo.x = x

class Bar(Foo):
x = 12

>>> a = Foo()
>>> a.munge_x(15)
>>> print a.x
15

>>> y = Bar()
>>> y.munge_x(15)
>>> print y.x
12

But if I change Foo to:

class Foo:
x = 9
def munge_x(self, x):
self.__class__.x = x

and try the same thing, I get the more intuitive:

>>> a = Foo()
>>> a.munge_x(15)
>>> print a.x
15

>>> y = Bar()
>>> y.munge_x(15)
>>> print y.x
15

It's just that writing self.__class__ is so *ugly*! Everything else
in Python is beautiful, too, which makes this stand out even more.


Neel

Joshua Rosen

unread,
Jun 23, 1999, 3:00:00 AM6/23/99
to
Zigron wrote:
>
> > Among all the suggestions for Python 2.0, removing the necessity of
> > prefixing methods and instance variables with "self." (and not having
> > to list it as an argument, either) would be my #1 wish.
>
> Whyfor? I personally like the seperate scopes, beween the class
> and the method. It makes it so I don't have to clean up as much. I can
> use as many temporary variables as I want in a method, and as soon
> as that method is gone...... its gone.

The other reason is that explicitely using a self-reference for instances goes
along with the method of calling unbound class-methods, and allows one to
easily `fake' membership of an instance in a class.

> I thought pv2 was going to
> objectify eeeeverything. (I can't tell you how much I want strings
> turned into objects! "blah".append('hi') should return 'blahhi'! :-))

Last I checked, everything in Python already was an object;)
Strings -are- objects--they just don't belong to a class or have any
properties/members/whateveryouwanttocallthem (some non-class--`top-level' I
suppose they should be called--objects do have members, like lists and
imaginary numbers).
I rather like the var-name-subsitution that PERL and Ruby and some other
languages do (ie: $something="bar"; "foo$something" == "foobar"), because it
shortens code, and sometimes makes it much prettier (having stripped out all of
the `end string, use an operator, reference something, resume new string'
procedures); Python's %-replacement is nice, too, though a bit more lengthy.

One thing to remember: languages all have their strengths and weaknesses, and
-rarely- is a language best for -everything-.

(back on track with the start of the thread: yeah, the shortcut operators
wouldn't really work well with Pythonic `assingment'/name-binding and immutable
objects).

-Rozzin.


Greg Ewing

unread,
Jun 24, 1999, 3:00:00 AM6/24/99
to
Bernhard Reiter wrote:
>
> += just saves some space and typing time.

It's not quite as simple as that, because

a[i] = a[i] + expr

and

a[i] += expr

would be semantically different if the former
did the index lookup only once. However, there
are serious difficulties with trying to incorporate
such semantics into Python's execution model,
and the consensus among experienced Python
implementation hackers seems to be that the results
would be Not Worth The Bother (tm).

Greg

Alexander Williams

unread,
Jun 24, 1999, 3:00:00 AM6/24/99
to
On 23 Jun 1999 20:56:41 -0500, Neel Krishnaswami <ne...@brick.cswv.com> wrote:
>It's just that writing self.__class__ is so *ugly*! Everything else
>in Python is beautiful, too, which makes this stand out even more.

Er, that could be because you're doing it wrong? Try:

class Foo:
def __init__(me):
me.x = 9

def setX(me, val):
me.x = val

>>> y = Foo()
>>> y.x
9
>>> y.setX(12)
>>> y.x
12

If you /really/ want to go frobbing around with the value that all
instances of the class inherit from, instance.__class__.slot is likely
a /great/ way of pointing out to the reader you're doing something
funky (in that classes are usually thought of as immutable, despite
the reality). The 'unsightly' nature of the construct makes it clear
you're doing something unasthetic.

--
Alexander Williams (tha...@gw.total-web.net)
"In the end ... Oblivion Always Wins."

Reimer Behrends

unread,
Jun 24, 1999, 3:00:00 AM6/24/99
to
Zigron (zig...@jps.net) wrote:
> Reimer Behrends <behr...@cse.msu.edu> wrote in message
> news:slrn7n0rr2....@allegro.cse.msu.edu...
[...]

> > Among all the suggestions for Python 2.0, removing the necessity of
> > prefixing methods and instance variables with "self." (and not having
> > to list it as an argument, either) would be my #1 wish.
>
> Whyfor? I personally like the seperate scopes, beween the class
> and the method. It makes it so I don't have to clean up as much. I can
> use as many temporary variables as I want in a method, and as soon
> as that method is gone...... its gone.

I said nothing like that. I am simply saying that the syntax is a
major pain. To remind you, pretty much every single OO language other
than Python does not require you to add a self; yet at the same time
they have per-method and per-object data. It's a matter of how you
declare it.

> The self.attribute thing makes sense. Each object has its own scope,
> er, namespace, whatever. Methods are considered objects, as are
> classes. Removing the 'self' requirement would, to me, change that.
> Methods wouldn't be objects anymore. :) At least it seems so to me,

I'm sorry, but I cannot make much sense of what you try to say here.
Could you perhaps elaborate?

[...]

Reimer Behrends

Alan Gauld

unread,
Jun 24, 1999, 3:00:00 AM6/24/99
to
Reimer Behrends wrote:
> _am_ getting pretty sick of having to type self.whatever countless
> times, where pretty much any other language allows me to discard the
> "self." part. Not only is it annoying to type, it also reduces the
> readability of OO code a lot, much like the gratuitious use of
> punctuation characters as variable prefixes in Perl does.

I used to think that, but after some time in python land I
just finished reviewing the code of a C++ project (about
5,000 new lines, 7 new classes in a system with 200,000
lines and about 200 classes.).

I was amazed to discover how difficult it was to understand
the code because I couldn't identify which variables were
local to the function, which were instance variables and
which were global.

This gets worse when dealing with multiple inheritance,
I wound up spend significant time in the headers directory
doing grep... The self notation makes it clear and pretty
unambiguous.

Alan G.

--
=================================================
This post represents the views of the author
and does not necessarily accurately represent
the views of BT.

Preston Landers

unread,
Jun 24, 1999, 3:00:00 AM6/24/99
to
cat...@my-deja.com writes:

> I've got the following in my .vimrc file:
> au BufReadPost * if b:current_syntax == "python"
> au BufReadPost * map! += ^[:s/\(\S*\)$/\1=\1+/^M:noh^MA
> au BufReadPost * endif

I'm thinking of doing a similar thing in (X)Emacs. It's my editor of
choice though I've never actually *programmed* something into emacs
itself. I'm wondering if anyone's already done a similar thing so I
can spare the trouble (and the learning exercise, bah.)

I'm thinking the best way might be to hook in to abbrev mode or
something... I guess I have some homework to do in this area. I was
just wondering if someone's already done something like this.

In case you're just joining this thread, the general idea is to have
your editor expand this:

foo += 1

to this:

foo = foo + 1

In theory it sounds easy enough. It's just a simple matter of
programming.

Thanks,

---Preston


Joshua Rosen

unread,
Jun 24, 1999, 3:00:00 AM6/24/99
to
Reimer Behrends wrote:
> To remind you, pretty much every single OO language other
> than Python does not require you to add a self; yet at the same time
> they have per-method and per-object data. It's a matter of how you
> declare it.

Of course, Python doesn't have pre-assignment declarations of variables....

-Rozzin.


Michael P. Reilly

unread,
Jun 24, 1999, 3:00:00 AM6/24/99
to
Joshua Rosen <roz...@geekspace.com> wrote:

Not quite true.. global variables must declared as such within a local
scope, even before any assignment.

$ cat foo.py
def foo():
global bar
bar = "Joe's"
foo()
print bar
$ python foo.py
Joe's
$

Formal function parameters (which are placed in the local namespace)
must be declared before envocation.

So there are five ways to..

No, two sir!

But it IS true that within functions (and methods and class definitions
and...) that unqualified local variable names do not have to be
declared.

It is also true that a lot of speghetti code can more easily come out
of "OO" languages with intermeshed object namespaces (this said as a
software configuration manager of many years, organizations and
projects writing in different OO languages). Having to qualify the
names leads to fewer scoping problems down the road (when someone else
is picking up the code and porting it).

-Arcege


Neel Krishnaswami

unread,
Jun 24, 1999, 3:00:00 AM6/24/99
to
In article <slrn7f68br....@brimstone.mecha>,

Alexander Williams <tha...@gw.total-web.net> wrote:
>On 23 Jun 1999 20:56:41 -0500, Neel Krishnaswami <ne...@brick.cswv.com> wrote:
>>It's just that writing self.__class__ is so *ugly*! Everything else
>>in Python is beautiful, too, which makes this stand out even more.
>
>Er, that could be because you're doing it wrong? Try:
>
>class Foo:
> def __init__(me):
> me.x = 9
>
> def setX(me, val):
> me.x = val

IMO, it's bad style to set properties that should belong to the type
in the instance initializer -- for example, the sort order is
something that's a property of the class, rather than the instances.

Here's an example from some code of mine (it's from a programmatic
front-end to Dejanews):

class Article:
[...]
#
# To set the sort order, set Article.sortorder to one of the
# keys of Article.comparators.
#
comparators = {'date': lambda x,y: cmp(x.date,y.date),
'score': lambda x,y: cmp(x.score,y.score),
'author': lambda x,y: cmp(x.author,y.author),
'subject': lambda x,y: cmp(x.subject,y.subject),
'newsgroup': lambda x,y: cmp(x.newsgroup,y.newsgroup)
}
sortorder = 'date' # can be anything in Article.comparators.keys()

[...]

def __cmp__(self, other):
return self.__class__.comparators[self.__class__.sortorder](self,
other)

I want the user to be able to determine how a list of Article's can be
sorted by setting the class's sortorder member. So a statement like

>>> Article.sortorder = 'author'

would change how lists of articles are sorted. This is definitely
something that's shouldn't be an instance attribute, imo; it would
defeat the purpose if each article could compare differently than
any other. (Oppose standardized testing! :])

But look how ugly that __cmp__ method is; it would be a lot clearer to
write something like

def __cmp__(self, other):
return Article.comparators[Article.sortorder](self, other)

because that would make it clearer what class state is being used, and
why. However, though it would be clearer to the programmer, it would
profoundly mess up inheritance.

It's perfectly reasonable for someone else to subclass Article and
override the Article.comparators attribute. (Say to add an ordering to
put Tim Peter's posts at the top of the list, or to use something
faster than my lambdas.) With the clear way of writing it, the
NewArticle class would mysteriously fail to do the right thing,
because the __cmp__ method would look in the Article class dictionary
without bothering to check NewArticle's.

This is an unusual glitch in Python; usually the readable way of doing
something is the right way of doing it.

Maybe we could re-use the class keyword and let people write class.foo
inside class definitions, by analogy to writing self.foo to refer to
the current instance? And the class.foo syntax would get translated to
the equivalent of self.__class__?

Hmm. Might hairify the grammar a bit too much, though.


Neel

Alex Rice

unread,
Jun 24, 1999, 3:00:00 AM6/24/99
to
Preston Landers <plan...@mail.utexas.edu> writes:

> I'm thinking of doing a similar thing in (X)Emacs. It's my editor of
> choice though I've never actually *programmed* something into emacs
> itself. I'm wondering if anyone's already done a similar thing so I
> can spare the trouble (and the learning exercise, bah.)
>
> I'm thinking the best way might be to hook in to abbrev mode or
> something... I guess I have some homework to do in this area. I was
> just wondering if someone's already done something like this.

Not that I know of -- and that doesn't mean much --, but since I'm
always willing to learn more about Emacs (wink-wink, nudge-nudge),
here are some macros that kind of approximate it...

In Emacs, creating a macro is easy: C-x( [type stuff here] C-x)
Binding the macros to sensible keystrokes seems to be the hard part in
this case. I challenge you to find a way to integrate these into
emacs's python-mode. :-)

Put this in your .emacs

8< cut

;; Macros for Python
;; Alex Rice <al...@mindlube.com>

(defalias '++
(read-kbd-macro "C-SPC ESC b ESC w ESC f = C-y +1 C-e"))
(defalias '--
(read-kbd-macro "C-SPC ESC b ESC w ESC f = C-y -1 C-e"))
(defalias '+=
(read-kbd-macro "C-SPC ESC b ESC w ESC f = C-y + C-e"))
(defalias '-=
(read-kbd-macro "C-SPC ESC b ESC w ESC f = C-y - C-e"))
(defalias '*=
(read-kbd-macro "C-SPC ESC b ESC w ESC f = C-y * C-e"))
(defalias '/=
(read-kbd-macro "C-SPC ESC b ESC w ESC f = C-y / C-e"))

8< cut

Now for example typing

spam M-x++

yields

spam=spam+1

BTW, _Learning GNU Emacs_ by O'Reilly & Assoc is a good gentle intro
to Emacs if you are like me and sometimes can't figure it out just
from the Info browser.

Cheers,

Alex Rice

Greg Ewing

unread,
Jun 25, 1999, 3:00:00 AM6/25/99
to
Reimer Behrends wrote:
>
> To remind you, pretty much every single OO language other
> than Python does not require you to add a self;

And in some of those languages, some people have
resorted to naming conventions to keep the various
scopes under control.

In the Object Pascal version of MacApp, for example,
Apple adopted the convention of prefixing the names
of all instance variables with "f" (for "field").

Mind you, Apple's Object Pascal is a somewhat
pathological case, since it's scope rules for
instance variables and local variables are,
shall we say, rather unintuitive...

Greg

Reimer Behrends

unread,
Jun 25, 1999, 3:00:00 AM6/25/99
to
Alan Gauld (alan....@gssec.bt.co.uk) wrote:
["self" prefix vs. readability.]

> I was amazed to discover how difficult it was to understand
> the code because I couldn't identify which variables were
> local to the function, which were instance variables and
> which were global.

While I'd be the first to agree that C++ is not exactly the epitome of
language design, I would think that at least the local variables should
be easy to identify. The only real problem is to distinguish global
variables from instance variables. And this is made worse in C++ by
spreading all the information related to a class over more than one
file. It should be noted that other languages do not necessarily have
the same problem and that careful design can easily avoid it.

But I do not think that the most basic operations of an OO language
should be complicated by cumbersome syntax (this includes instance
variable access and local method calls). The language should encourage
use of these elements, not get in your way.

[...]

Reimer Behrends

Alexander Williams

unread,
Jun 25, 1999, 3:00:00 AM6/25/99
to
On 24 Jun 1999 21:09:19 -0500, Neel Krishnaswami <ne...@brick.cswv.com> wrote:
>IMO, it's bad style to set properties that should belong to the type
>in the instance initializer -- for example, the sort order is
>something that's a property of the class, rather than the instances.

Here's the crux of the problem, a sense of asthetics at variance with
the usefullness of your code. Allow me to present a dissenting view:

Setting properties which can vary dynamically over the life of an
instance should be set on the instance itself, since the Class itself
may have multiple instantiations in a multithreaded or
multi-persistance environment. Ultimately, it becomes easier to note
and manage varying fields on instances as they are easily seen in the
__init__ function (and so satisfy lexical locality in finding them for
maintainance) as well as cuts back on strange circumlocutions in
dealing with them syntactically.

> sortorder = 'date' # can be anything in Article.comparators.keys()

Let's assume you set this in the __init__:

def __init__(me):
me.sortorder = 'date'

> def __cmp__(self, other):
> return self.__class__.comparators[self.__class__.sortorder](self,
> other)

.... then this becomes:

def __cmp__(me, them):
return me.comparators[me.sortorder](me, them)

Note that comparators is set on the instance by inheritance, so we
don't need to obscure that with a specialized __class__ reference, and
with sortorder being an instance variable, there's no need for
obscuration /there/, either.

>I want the user to be able to determine how a list of Article's can be
>sorted by setting the class's sortorder member. So a statement like
>
>>>> Article.sortorder = 'author'
>
>would change how lists of articles are sorted. This is definitely
>something that's shouldn't be an instance attribute, imo; it would
>defeat the purpose if each article could compare differently than
>any other. (Oppose standardized testing! :])

In this case, the order in which articles are sorted shouldn't be on
the Article object at all, then! Remember, encapsulation,
encapsulation. Sort-order storage should be on the object that you
use to contain references to Article-objects, and thus only needs to
be changed in one place at one time (but still should be an instance
variable, since it does change dynamically and shouldn't be inherited
by all children of ArticleStore, since each may want to be sorted in a
different way, providing different views into the same data).

>It's perfectly reasonable for someone else to subclass Article and
>override the Article.comparators attribute. (Say to add an ordering to
>put Tim Peter's posts at the top of the list, or to use something
>faster than my lambdas.) With the clear way of writing it, the
>NewArticle class would mysteriously fail to do the right thing,
>because the __cmp__ method would look in the Article class dictionary
>without bothering to check NewArticle's.

See above; note that calling me.comparators will /always/ work with
inheritance.

>This is an unusual glitch in Python; usually the readable way of doing
>something is the right way of doing it.

Ah, but it /is/ the right way, you're just insisting on the wrong way
out of a twisted sense of asthetics. :)

Jesse Sweeney

unread,
Jun 25, 1999, 3:00:00 AM6/25/99
to
On 23 Jun 1999 20:56:41 -0500, ne...@brick.cswv.com (Neel Krishnaswami) wrote:

[ snip -- complaints about having to write 'self' over and over ]

>I don't mind writing self.foo = bar, for the reason you describe, but
>I know I hate having to write self.__class__.member = foo in order to
>keep inheritance from breaking:
>
>class Foo:
> x = 9
> def munge_x(self, x):
> Foo.x = x
>
>class Bar(Foo):
> x = 12

^^^
This creates an attribute Bar.x

>
>>>> a = Foo()
>>>> a.munge_x(15)
>>>> print a.x
>15
>
>>>> y = Bar()
>>>> y.munge_x(15)
>>>> print y.x
>12

^^^
Here, y.x evaluates to Bar.x

The problem is that a call to munge_x is munging Foo.x no matter what the self
parameter turns out to be. So, if self is an object with it's own x attribute,
whether as an instance attribute, or as a class attribute lower down in the
heirarchy, that attribute will mask the attribute of the same name in Foo (sorry
about that long sentence). ie: self.x isn't always the same as Foo.x.
I don't really see what's unintuitive about this. You could just write:

class Bar(Foo):
pass

>
>But if I change Foo to:
>
>class Foo:
> x = 9
> def munge_x(self, x):
> self.__class__.x = x
>
>and try the same thing, I get the more intuitive:
>
>>>> a = Foo()
>>>> a.munge_x(15)
>>>> print a.x
>15
>
>>>> y = Bar()
>>>> y.munge_x(15)
>>>> print y.x
>15

This is a different kettle of fish. Note:

>>> a = Foo()
>>> a.munge_x(15)


>>> a.x
15
>>> y = Bar()

>>> y.munge_x(20)
>>> y.x
20
>>> a.x
15

>
>It's just that writing self.__class__ is so *ugly*! Everything else
>in Python is beautiful, too, which makes this stand out even more.

Cheers, Jesse


Tim Peters

unread,
Jun 25, 1999, 3:00:00 AM6/25/99
to pytho...@python.org
[Reimer Behrends]

> While I'd be the first to agree that C++ is not exactly the epitome of
> language design, I would think that at least the local variables should
> be easy to identify. The only real problem is to distinguish global
> variables from instance variables. And this is made worse in C++ by
> spreading all the information related to a class over more than one
> file. It should be noted that other languages do not necessarily have
> the same problem and that careful design can easily avoid it.

But even with declarations up the wazoo, distinguishing local from instance
vars is a major problem in real-life C++: 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 (e.g., Java
flatly prohibits shadowing in most cases -- but specifically allows this
one).

Any reasonably careful programmer will avoid such shadowing when the code is
first written, but under time & modification that never lasts; perhaps just
because the names most natural to a problem domain are limited.

So I've never worked on a (successful <0.9 wink>) C++ project where coding
conventions didn't require prefixing instance vars with some magical
sequence reserved for that purpose. The one I'm working on now requires
member var names to match the case-sensitive regexp

^m[A-Z]\w*

and similarly starting with "g" for extern data and "s" for file-static data
(local names are "anything else"). Other projects enforced other
conventions -- it's a real relief to come back to Python and see it always
spelled "self."!

> But I do not think that the most basic operations of an OO language
> should be complicated by cumbersome syntax (this includes instance
> variable access and local method calls). The language should encourage
> use of these elements, not get in your way.

Readability is more important to me over the long haul. 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.

explicitly-favoring-explict-ly y'rs - tim

Michael Hudson

unread,
Jun 25, 1999, 3:00:00 AM6/25/99
to
ne...@brick.cswv.com (Neel Krishnaswami) writes:

>
> It's just that writing self.__class__ is so *ugly*! Everything else
> in Python is beautiful, too, which makes this stand out even more.
>

You want ugly? I think the whole area of calling base class functions
is far uglier.

You might have a base class like this:

class C:
def f(self,x):
print self

then a derived class that needed to call C.f would have to be written:

class D(C):
def f(self,x):
C.f(self,x)
print x

I think needing `self' here sucks. It gets worse if there are keyword
arguments, necessitating use of apply, or if the base class is in a
different module.

This can be combined with another irritation of mine, the lack of
automatic initialization of base classes, to give a situation like
this:

base.py:

class Base:
def __init__(self,x,y,**kw):
...

derived.py:

import base

class Derived(base.Base):
def __init__(self,x,y,z,**kw):
apply(base.Base.__init__,(self,x,y),kw)
print z

which I think is one of the ugliest things I've ever seen in Python
that I couldn't think of a prettier way round. Ideas, anyone?

twisted-ly y'rs
Michael

Alan Gauld

unread,
Jun 25, 1999, 3:00:00 AM6/25/99
to
Reimer Behrends wrote:
> While I'd be the first to agree that C++ is not exactly the epitome of
> language design, I would think that at least the local variables should
> be easy to identify. The only real problem is to distinguish global

Not so. If the method is long(as these were - over 200 lines
in some cases, mostly initialising huge DCE Data structures)
you can't see the local definitions. C++ compounds this with
its ability to declare local variables anywhere in the code
(so a split screen editor doesn't help).

Joshua Rosen

unread,
Jun 25, 1999, 3:00:00 AM6/25/99
to
Neel Krishnaswami wrote:
> Maybe we could re-use the class keyword and let people write class.foo
> inside class definitions, by analogy to writing self.foo to refer to
> the current instance? And the class.foo syntax would get translated to
> the equivalent of self.__class__?

How about defining __getattr__ and company?

-Rozzin.


Reimer Behrends

unread,
Jun 26, 1999, 3:00:00 AM6/26/99
to
Alan Gauld (alan....@gssec.bt.co.uk) wrote:
[...]

> Not so. If the method is long(as these were - over 200 lines
> in some cases, mostly initialising huge DCE Data structures)
> you can't see the local definitions. C++ compounds this with
> its ability to declare local variables anywhere in the code
> (so a split screen editor doesn't help).

A program shouldn't have methods that are 200 lines long; as a rule of
thumb, any method should fit on a single screen (and I mean 80x24, not a
maximized xterm on a 21" monitor). And most methods should be much
shorter than that. If the code you have is screwed up like that, you
have much worse problems than scoping problems. If you need to
initialize large data structures, the initialization process needs to
be broken down into manageable entities (which can then be composed
and reused).

Reimer Behrends


Reimer Behrends

unread,
Jun 26, 1999, 3:00:00 AM6/26/99
to
Tim Peters (tim...@email.msn.com) wrote:
> [Reimer Behrends]

> > While I'd be the first to agree that C++ is not exactly the epitome of
> > language design, I would think that at least the local variables should
> > be easy to identify. The only real problem is to distinguish global
> > variables from instance variables. And this is made worse in C++ by
> > spreading all the information related to a class over more than one
> > file. It should be noted that other languages do not necessarily have
> > the same problem and that careful design can easily avoid it.
>
> But even with declarations up the wazoo, distinguishing local from instance
> vars is a major problem in real-life C++: any OO language with declarations
> has to allow local vars to shadow instance vars,

To the contrary; Eiffel, under no circumstances allows shadowing of
instance variables by formal parameters or by local variables. 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. (And I prefer compilers that are
too picky rather than too lenient.)

> else method implementations
> can be broken by trivial changes in far-removed superclasses (e.g., Java
> flatly prohibits shadowing in most cases -- but specifically allows this
> one).

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.

Of course, there are languages that don't have this problem. For
instance, in either Smalltalk or Eiffel, there are no modules outside
the class concept, and a variable is either local (which you can easily
see in the method declaration, or an attribute.

But I digress ...

[...]


> > But I do not think that the most basic operations of an OO language
> > should be complicated by cumbersome syntax (this includes instance
> > variable access and local method calls). The language should encourage
> > use of these elements, not get in your way.
>
> 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.

> 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


Tim Peters

unread,
Jun 26, 1999, 3:00:00 AM6/26/99
to pytho...@python.org
[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

Greg Ewing

unread,
Jun 28, 1999, 3:00:00 AM6/28/99
to
Michael Hudson wrote:
>
> class Derived(base.Base):
> def __init__(self,x,y,z,**kw):
> apply(base.Base.__init__,(self,x,y),kw)
> print z
>
> which I think is one of the ugliest things I've ever seen in Python
> that I couldn't think of a prettier way round. Ideas, anyone?

Yes! With the calling syntax extension that I
have proposed before, that would be written

Base.__init__(self, x, y, **kw)

Still requires the self argument, but I think
you'll agree it's a lot better than having to
use apply!

I'd also like a way of getting rid of the self
argument in that situation as well, but this seems
to be quite a difficult problem to solve within
Python's existing execution model. I haven't
thought of a good solution yet.

Greg

Tim Peters

unread,
Jun 28, 1999, 3:00:00 AM6/28/99
to pytho...@python.org
[Neel Krishnaswami]
> ...

> Here's an example from some code of mine (it's from a programmatic
> front-end to Dejanews):
>
> class Article:
> [...]
> #
> # To set the sort order, set Article.sortorder to one of the
> # keys of Article.comparators.
> #
> comparators = {'date': lambda x,y: cmp(x.date,y.date),
> 'score': lambda x,y: cmp(x.score,y.score),
> 'author': lambda x,y: cmp(x.author,y.author),
> 'subject': lambda x,y: cmp(x.subject,y.subject),
> 'newsgroup': lambda x,y: cmp(x.newsgroup,y.newsgroup)
> }
> sortorder = 'date' # can be anything in Article.comparators.keys()
>
> [...]

>
> def __cmp__(self, other):
> return self.__class__.comparators[self.__class__.sortorder](self,
> other)
>
> I want the user to be able to determine how a list of Article's can be
> sorted by setting the class's sortorder member. So a statement like
>
> >>> Article.sortorder = 'author'
>
> would change how lists of articles are sorted. This is definitely
> something that's shouldn't be an instance attribute, imo; it would
> defeat the purpose if each article could compare differently than
> any other. (Oppose standardized testing! :])
>
> But look how ugly that __cmp__ method is; it would be a lot clearer to
> write something like
>
> def __cmp__(self, other):
> return Article.comparators[Article.sortorder](self, other)
>
> because that would make it clearer what class state is being used, and
> why. However, though it would be clearer to the programmer, it would
> profoundly mess up inheritance.
>
> It's perfectly reasonable for someone else to subclass Article and
> override the Article.comparators attribute. (Say to add an ordering to
> put Tim Peter's posts at the top of the list,

Yes, an excellent idea!

> or to use something faster than my lambdas.)

Oh, yawn <wink>.

> With the clear way of writing it, the NewArticle class would
> mysteriously fail to do the right thing, because the __cmp__ method
> would look in the Article class dictionary without bothering to check
> NewArticle's.

The trap is hard to avoid, though: if a direct instance of Article is
"self", and a direct instance of NewArticle is "other", even keying off
self.__class__.etc is a surprise (well, at least to "other"!). In part
you're taking a single-dispatch approach to a problem with multiple-dispatch
headaches. Face that head-on and you'll write a multiple-argument
dispatcher with which the various classes need to register their intentions
("OK, if arg1 and arg2 are both Articles, I need to compare such-&-such a
way; if arg1 is Article but arg2 is NewArticle, that-&-that a way;" etc).
Then it's factored out of the xxxArticle classes.

> This is an unusual glitch in Python; usually the readable way of doing
> something is the right way of doing it.

Guido long ago confessed he had static class hierarchies in mind, where
everyone knew who they were inheriting from for all time so that "super" etc
weren't needed. That should probably be re-thought for Python2, since it
has come up more than once <wink>. Writing

class A(B):
def __init__(self, x, y, z):
B.__init__(self, x, y, z)

can be grating too (hmm ... I see Michael and Greg are whining about that
too, so I'll skip it).

In your particular case, the solution that plays along with the current
design is to forget direct access *and* __class__, instead indirecting
through a method:

class Article:
comparators = { ... }
sortorder = { ... }
def get_class_comparators(self):
return Article.comparators
def get_class_sortorder(self):
return Article.sortorder
def __cmp__(self, other):
return self.get_class_comparators() ...

and override get_class_comparators/sortorder() in NewArticle. Perfectly
clear and ridiculously involved <wink>. The fact is that self.comparators
does the search that you want, so that's the best way to do it -- live with
a comment.

> Maybe we could re-use the class keyword and let people write class.foo
> inside class definitions, by analogy to writing self.foo to refer to
> the current instance? And the class.foo syntax would get translated to
> the equivalent of self.__class__?

Except that you want class.foo to act like self.__class__.foo <wink>. Guido
certainly won't change this in Python1 regardless; take it up on the
Types-SIG for Python2!

more-dead-ideas-there-than-in-kosovo-ly y'rs - tim

Bernhard Reiter

unread,
Jun 28, 1999, 3:00:00 AM6/28/99
to
On Thu, 24 Jun 1999 09:27:16 +1200, Greg Ewing <greg....@compaq.com> wrote:
>Bernhard Reiter wrote:
>> += just saves some space and typing time.
>It's not quite as simple as that, because
>
> a[i] = a[i] + expr
>and
> a[i] += expr
>
>would be semantically different if the former
>did the index lookup only once.
True.
I guess that using multiple evaluations and their side effects
are a not a good thing anyway. :)
And the python interpreter might optimise the former... >;-)
Bernhard


--
Research Assistant, Geog Dept UM-Milwaukee, USA. (www.uwm.edu/~bernhard)
Funding/Promoting Association for a Free Informational Infrastructure (ffii.org)

Greg Ewing

unread,
Jun 29, 1999, 3:00:00 AM6/29/99
to
Tim Peters wrote:
>
> class A(B):
> def __init__(self, x, y, z):
> B.__init__(self, x, y, z)
>
> can be grating too

I could live with having to explicitly name the
superclass, provided something checked that the
class I named was actually a direct base class
of the one where the method is defined. That
way things would be less likely to break
mysteriously when I rearrange the class
hierarchy.

I'm still thinking about how to implement
this...

Greg

Reimer Behrends

unread,
Jun 29, 1999, 3:00:00 AM6/29/99
to
Tim Peters (tim...@email.msn.com) wrote:
[...]

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

These are two different things, actually. If you forbid shadowing of
instance variables by local variables, then simply renaming the local
variable in the subclass can fix the problem. This is applicable to
any language.

The related problem of adding a new method or attribute to a superclass
that already exists in a subclass, while most easily solved by a renaming
mechanism, is also amenable to a minor rewrite of the subclass. I am
assuming, of course, that you have a system where the compiler notifies
you if you accidentally redefine a method.

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

Adding methods or instance variables to a superclass is never "trivial".
It always has the potential of breaking existing subclasses.

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

Yes. This is why changes to a superclass are always critical. However,
a well-designed subclass should always be able to recover by simply
changing the names of conflicting entities. It will always entail a
change to the subclass, however.

[...]


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

I am aware of that. That's why I suggested that the "self." notation is
not too much different. Because more often than not it _is_ entirely
clear from the context what you are doing. And in these cases the
required qualification is needless visual overhead, just like Hungarian
notation (in fact, it is probably even worse).

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

Then why do we have "from module import name"? :)

The point I am trying to make is that sometimes making a qualification is
redundant, if the context is already known. In this case the unambiguity
of the reference comes at the cost of cluttering the code with extraneous
tokens. This is exacerbated by the fact that "self" does not stand out
and that you easily get more tokens per line than your short-term memory
is comfortable with.

Come to think of it, why don't we require that _local_ variables be
qualified, too? For instance:

for local.item in local.list:
local.sum = local.sum + local.item

It is, I think, the assumption that local variables are the default
case; that _most_ of the time you operate on local variables, and
you don't want to clutter your code. But in an OO language that
assumption no longer is true; you are going to operate on instance
variables just as often. The same reasoning that leads to local
variables not being qualified can be applied to methods operating
on instance variables.

For instance, I noticed that I much preferred the way Ruby denotes
attributes, even though it uses a superficially similar approach (Ruby
prefixes attributes with an "@" symbol rather than with "self."). So,
for instance, instead of

self.last = self.lines[-1]
self.lines = self.lines[:-1]

we have something like:

@last = @lines[-1]
@lines = @lines[:-1]

While I'm not that happy with this kind of notation, either, I find it
much easier to pick out what exactly is going on.

Ideally, of course, the code would look like:

last = lines[-1]
lines = lines[:-1]

and it should be made obvious from the context whether last/lines are
local or instance variables.

[Perl's prefix symbols.]


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

I am fully aware of this and I agree that they are a very necessary evil
in Perl. The point, however, remains that many people do regard Perl as
being less legible because of this.

[...]

> So the decorations solve a problem in Perl that Python doesn't have, so they
> make good sense in Perl but not in Python.

Pardon me, but I disagree here; these symbols provide annotations that
tell you which type a certain variable has. Since Python does not allow
you to declare that a variable is of a certain type, you have to rely
on conventions to ensure that there is no misunderstanding. In a mailing
list manager, is "list" really a list, or instead a string that contains
the name of the mailing list?

But apparently this isn't a big problem, which implies that it is
possible to deal with the absence of declarations in a way that doesn't
require you to qualify each and every use of an entity and still come
up with maintaineable code.

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

I would prefer to go into the opposite direction, actually. Using
something like global to denote attributes. For instance:

attr last, lines

last = lines[-1]
lines = lines[:-1]

Reimer Behrends

Tim Peters

unread,
Jun 29, 1999, 3:00:00 AM6/29/99
to pytho...@python.org
>> class A(B):
>> def __init__(self, x, y, z):
>> B.__init__(self, x, y, z)
>>
>> can be grating too

[Greg Ewing]


> I could live with having to explicitly name the
> superclass, provided something checked that the
> class I named was actually a direct base class
> of the one where the method is defined. That
> way things would be less likely to break
> mysteriously when I rearrange the class
> hierarchy.
>
> I'm still thinking about how to implement
> this...

Hard! Class attrs (like __init__) don't point back to the class they belong
to. In the absence of sharing, though, the class chain can be searched for
the class that owns a particular attr value. I'll attach something that
does that; it's ugly; I'll never use it <wink>; could speed it a lot by
caching the search result.

seems-a-lot-easier-to-do-it-by-eye-ly y'rs - tim

class BaseInit:
"""A mixin class for "safe" superclass __init__ calls.

class X(Y, Z, ..., BaseInit):
def __init__(self, whatever):
self.baseinit(K, whatever)

self.baseinit(K, whatever) invokes K.__init__(self, whatever), but
raises an error unless K is a direct base class of X (the class
in which the __init__ calling baseinit is defined).
"""

def baseinit(self, base, *args, **kwargs):
import sys
if not isinstance(self, base):
raise TypeError(`self` + " isn't even an instance of " +
`base`)
# init <- code object of __init__ we were called from
try:
raise 'bogus'
except 'bogus':
tb = sys.exc_info()[2]
init = tb.tb_frame.f_back.f_code # back to the __init__
if init.co_name != "__init__":
raise ValueError("baseinit must be called from __init__")
# search the class hierarchy for that __init__, setting
# c to the class it belongs to
candidates = [self.__class__]
while candidates:
c = candidates.pop(0)
if c.__dict__.has_key("__init__"):
cinit = c.__init__.im_func.func_code
if init is cinit:
break
candidates = list(c.__bases__) + candidates
else:
raise SystemError("didn't find __init__ in class or bases!")
if base not in c.__bases__:
raise TypeError("attempt to init superclass " + `base` +
" from " + `c` + " but the "
"superclass isn't an immediate base class")
apply(base.__init__, (self,) + args, kwargs)

class A:
def __init__(self):
print "in A's init"

class B(A, BaseInit):
def __init__(self):
print "in B's init"
self.baseinit(A)

class C(B, BaseInit):
def __init__(self):
print "in C's init"
self.baseinit(B)
print "next one should be bogus"
self.baseinit(A)

b = B()
c = C()

Guido van Rossum

unread,
Jun 29, 1999, 3:00:00 AM6/29/99
to
Greg Ewing <greg....@compaq.com> writes:

> > class A(B):
> > def __init__(self, x, y, z):
> > B.__init__(self, x, y, z)
>

> I could live with having to explicitly name the
> superclass, provided something checked that the
> class I named was actually a direct base class
> of the one where the method is defined. That
> way things would be less likely to break
> mysteriously when I rearrange the class
> hierarchy.

Oh, but that check *is* being made! (In fact this is the same check
that prevents "class methods" from working ;-)

>>> class A:
def __init__(self):
self.a = 1


>>> class B:
def __init__(self):
self.b = 1


>>> class C(B):
def __init__(self):
A.__init__(self)


>>> C()
Traceback (innermost last):
File "<pyshell#12>", line 1, in ?
C()
File "<pyshell#11>", line 3, in __init__
A.__init__(self)
TypeError: unbound method must be called with class instance 1st argument
>>>

--Guido van Rossum (home page: http://www.python.org/~guido/)

Bernhard Herzog

unread,
Jun 29, 1999, 3:00:00 AM6/29/99
to
behr...@cse.msu.edu (Reimer Behrends) writes:

> For instance, I noticed that I much preferred the way Ruby denotes
> attributes, even though it uses a superficially similar approach (Ruby
> prefixes attributes with an "@" symbol rather than with "self."). So,
> for instance, instead of
>
> self.last = self.lines[-1]
> self.lines = self.lines[:-1]
>
> we have something like:
>
> @last = @lines[-1]
> @lines = @lines[:-1]
>

I think a better solution that better fits the python syntax is to
simply omit the self but not the dot:

.last = .lines[-1]
.lines = .lines[:-1]

That is, if one really wanted to have a shorthand for instance variables
in methods.


--
Bernhard Herzog | Sketch, a python based drawing program
her...@online.de | http://www.online.de/home/sketch/

Joshua Rosen

unread,
Jun 29, 1999, 3:00:00 AM6/29/99
to
Reimer Behrends wrote:
> 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. :)

+There is no difficulty in getting the program to know what type some piece of
data is, which lessens the need for the type-declaring prefixes--use type(),
and then check obj.__class__ if obj is a class-instance, and you need to -know-
what class it is (if you want to -force- it to be a certain type, keep
reading).
+Requiring variables to bear a prefix denoting type sortof makes Python into a
statically-typed language, where one of the big reasons for using it is that
it's a dynamically-typed language.
+There is no such thing as a `scalare', in Python--strings and numbers are
different data-types, numeric data can actually be one of many different
classes.
+Forcing data to be of a specific type is already possible--see documentation
on int(), str(), list(), tuple(), float(), long(), complex(), string.atoi(), et
al. This functionality also lessens, if not completely eliminates the need for
typing prefixes; the program knows what type the data is being coered into, and
so does the programmer. In fact, all of the functionality that you're proposing
(and then some) is already there--it just looks different.
+If you really want a feature that -really- isn't offered by a language, the
best decision may be to just use another language that -does- offer it. Try
Pike, for one (I suggest it because it has nifty typing which you may like: you
can declare a variable to be one or -more- types, or use a mixed type). Choose
your languages based upon what you need them to do.


-Rozzin.


Tim Peters

unread,
Jun 29, 1999, 3:00:00 AM6/29/99
to Guido van Rossum, pytho...@python.org
>>> class A(B):
>>> def __init__(self, x, y, z):
>>> B.__init__(self, x, y, z)

[Greg Ewing]


> I could live with having to explicitly name the
> superclass, provided something checked that the
> class I named was actually a direct base class
> of the one where the method is defined. That
> way things would be less likely to break
> mysteriously when I rearrange the class
> hierarchy.

[Guido]


> Oh, but that check *is* being made! (In fact this is the same check
> that prevents "class methods" from working ;-)

Nope, that's a different check. If C derives from B derives from A, this
check allows either C.__init__ or B.__init__ to be called from A.__init__
with an instance of A. Greg wants B.__init__ to be OK here, but not
C.__init__ (C is not a direct base class of the one (A) where the method
(A.__init__) is defined). IOW, he wants a way to restrict __init__ calls to
immediate bases of the class from which the __init__ is invoked, to e.g.
prevent level-skipping under class rearrangement.

I posted some ugly code to address that, but think it's really a job for a
text editor and a pair of eyeballs <wink>.

although-something-to-be-said-for-automating-the-eyeballs-ly y'rs - tim

Guido van Rossum

unread,
Jun 29, 1999, 3:00:00 AM6/29/99
to Tim Peters
> >>> class A(B):
> >>> def __init__(self, x, y, z):
> >>> B.__init__(self, x, y, z)
>
> [Greg Ewing]
> > I could live with having to explicitly name the
> > superclass, provided something checked that the
> > class I named was actually a direct base class
> > of the one where the method is defined. That
> > way things would be less likely to break
> > mysteriously when I rearrange the class
> > hierarchy.
>
> [Guido]
> > Oh, but that check *is* being made! (In fact this is the same check
> > that prevents "class methods" from working ;-)
>
> Nope, that's a different check. If C derives from B derives from A, this
> check allows either C.__init__ or B.__init__ to be called from A.__init__
> with an instance of A. Greg wants B.__init__ to be OK here, but not
> C.__init__ (C is not a direct base class of the one (A) where the method
> (A.__init__) is defined). IOW, he wants a way to restrict __init__ calls to
> immediate bases of the class from which the __init__ is invoked, to e.g.
> prevent level-skipping under class rearrangement.

Sigh. Indeed.

> I posted some ugly code to address that, but think it's really a job for a
> text editor and a pair of eyeballs <wink>.

Hm -- he may be right! I was reading some IDLE code the other day and
noticed that PyShell's close() method was calling
PyShellEditorWindow.close(self) while it didn't inherit from that
class at all... Turns out the actual method was defined in a common
base class -- a silent (and in this case harmless) bug, caused by,
indeed, a class restructuring. So there is a point to his wish. On
the other hand Python explicitly allows you to ignore base class
methods in overriding ones, and even constructors... (And then again,
there is something to say for requiring constructors to play be
slightly different rules -- certainly they don't have to duplicate the
signature of the base class constructor like regular methods need to
do.)

Enough,

Reimer Behrends

unread,
Jun 30, 1999, 3:00:00 AM6/30/99
to
Joshua Rosen (roz...@geekspace.com) wrote:
> Reimer Behrends wrote:
> > 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. :)

> +There is no difficulty in getting the program to know what type
> some piece of data is, which lessens the need for the
> type-declaring prefixes--use type(), and then check
> obj.__class__ if obj is a class-instance, and you need to -know-
> what class it is (if you want to -force- it to be a certain
> type, keep reading).

Ahem. I happen to know Python fairly intimately after I don't know how
many years of constant use. What I wrote above was mostly a tongue in
cheek comment (heck, I even said so). The point I was making was that
the very same argument that justifies a self prefix can also be used to
justify type prefixes--in fact, I pretty much paraphrased it from an old
posting by Tom Christiansen on 10/26/98 (the message id is
<710kg1$mr0$1...@csnews.cs.colorado.edu>)

> +Requiring variables to bear a prefix denoting type sortof makes
> Python into a statically-typed language, where one of the big
> reasons for using it is that it's a dynamically-typed language.

I never said otherwise. But the same argument can be used mutatis
mutandum to support a "self"-less notation. :)

> +There is no such thing as a `scalare', in Python--strings and
> numbers are different data-types, numeric data can actually be
> one of many different classes.

I know. It was a facetious argument.

> +Forcing data to be of a specific type is already possible--see
> documentation on int(), str(), list(), tuple(), float(), long(),
> complex(), string.atoi(), et al. This functionality also
> lessens, if not completely eliminates the need for typing
> prefixes; the program knows what type the data is being coered
> into, and so does the programmer. In fact, all of the
> functionality that you're proposing (and then some) is already
> there--it just looks different.

And I just happen to be aware of that, too.

> +If you really want a feature that -really- isn't offered by a
> language, the best decision may be to just use another language
> that -does- offer it. Try Pike, for one (I suggest it because it
> has nifty typing which you may like: you can declare a variable
> to be one or -more- types, or use a mixed type). Choose your
> languages based upon what you need them to do.

And I know Pike, too. In fact, I'm pretty familiar with it.

By the way, would you mind using shorter lines next time?

Reimer Behrends

Reimer Behrends

unread,
Jun 30, 1999, 3:00:00 AM6/30/99
to
Bernhard Herzog (her...@online.de) wrote:
[...]

> I think a better solution that better fits the python syntax is to
> simply omit the self but not the dot:
>
> .last = .lines[-1]
> .lines = .lines[:-1]

Such a syntax was proposed a few years ago for private variables,
IIRC, but was discarded because it had various problems.

And personally, I'd rather live with the inconvenience of the explicit
self rather than having Python's design obfuscated by some strange
syntax; syntax highlighting can go a long way towards making the current
state of affairs more manageable.

Reimer Behrends

Reimer Behrends

unread,
Jun 30, 1999, 3:00:00 AM6/30/99
to
From: behr...@cse.msu.edu (Reimer Behrends)

Reimer Behrends

unread,
Jun 30, 1999, 3:00:00 AM6/30/99
to
From: behr...@cse.msu.edu (Reimer Behrends)

Joshua Rosen

unread,
Jul 1, 1999, 3:00:00 AM7/1/99
to
Eckh--apparently, I had a dead-brain day, and took you much too
seriously.
Of course, there's got to be someone out there who needed to here that
stuff....

I imagine that you were using typing as a metaphor for scoping, and,
now that I see it, I can appreciate it.

It would be nice to have some non-mandatory scope-resolution
capabilities beyond self-referencing in instance-methods and `global'
statements.

What would be a different way of getting the effect of:

ClassX.foo(ClassY())
?

Have bound and unbound methods be different creatures, perhaps....

No, never mind, I suppose--thinking about it, so long as you can
assure `this variable is a class variable', then everything should be
fine. Actually, just adding the instance's namespace to the list of
namespaces searched, in methods, shouldn't be too bad to implement,
and probably wouldn't break any of the existing code, eh? [function
locals, instance locals, globals]?

-Rozzin.


Neel Krishnaswami

unread,
Jul 1, 1999, 3:00:00 AM7/1/99
to
In article <000d01bec11f$8f966e20$e19e2299@tim>,
Tim Peters <tim...@email.msn.com> wrote:
>[Neel Krishnaswami]

>
>> With the clear way of writing it, the NewArticle class would
>> mysteriously fail to do the right thing, because the __cmp__ method
>> would look in the Article class dictionary without bothering to check
>> NewArticle's.
>
>The trap is hard to avoid, though: if a direct instance of Article is
>"self", and a direct instance of NewArticle is "other", even keying off
>self.__class__.etc is a surprise (well, at least to "other"!). In part
>you're taking a single-dispatch approach to a problem with multiple-dispatch
>headaches.

<light dawns>

Of course! I had noticed I wasn't having this problem in Dylan, and
it somehow failed to occur to me that the only significant difference
between Dylan and Python (Dylan's multiple-dispatch object model)
might have something to do with it. :)


Neel

Joshua Rosen

unread,
Jul 1, 1999, 3:00:00 AM7/1/99
to
From: Joshua Rosen <roz...@geekspace.com>

Neel Krishnaswami

unread,
Jul 1, 1999, 3:00:00 AM7/1/99
to
From: ne...@brick.cswv.com (Neel Krishnaswami)

Greg Ewing

unread,
Jul 2, 1999, 3:00:00 AM7/2/99
to
Guido van Rossum wrote:
>
> Oh, but that check *is* being made!

No, it's not. The check I'm talking about would
cause the call to A.foo in class C below to
fail. (And it doesn't -- I've just tried it.)

class A:
def foo(self):
print "foo of A"

class B(A):
def foo(self):
print "foo of B"
A.foo(self)

class C(B):
"""Fred Coder originally wrote this
so it was C(A), then changed it and
forgot to update the method."""
def foo(self):
print "foo of C"
A.foo(self)

c = C()
c.foo()

Do you see what I mean now?
Greg

Greg Ewing

unread,
Jul 2, 1999, 3:00:00 AM7/2/99
to
Bernhard Herzog wrote:
>
> .last = .lines[-1]
> .lines = .lines[:-1]

Hey, I've just had an idea: allow an *empty*
name as an identifier. Then we could write:

class C:
def foo(,x,y):
.z = .z + x * y

and kill two birds with one syntax change!

Greg

Greg Ewing

unread,
Jul 2, 1999, 3:00:00 AM7/2/99
to
From: Greg Ewing <greg....@compaq.com>

Greg Ewing

unread,
Jul 2, 1999, 3:00:00 AM7/2/99
to
From: Greg Ewing <greg....@compaq.com>

M.A.Miller

unread,
Jul 6, 1999, 3:00:00 AM7/6/99
to
>>>>> "Reimer" == Reimer Behrends <Reimer....@p98.f112.n480.z2.fidonet.org> writes:

> And personally, I'd rather live with the inconvenience of
> the explicit self rather than having Python's design
> obfuscated by some strange syntax; syntax highlighting can
> go a long way towards making the current state of affairs
> more manageable.

Does anyone have a tweak for python-mode.el that will highlight
occurrences of self and self.?

Mike

Preston Landers

unread,
Jul 7, 1999, 3:00:00 AM7/7/99
to
In article <76u2rha...@four.npl.uiuc.edu>,
mil...@uiuc.edu wrote:

> Does anyone have a tweak for python-mode.el that will highlight
> occurrences of self and self.?

Hey Mike,

Yeah, I posted my 3 line patch to python-mode.el in a separate thread
just a minute ago.

If you can't find it or whatever, check here:

http://askpreston.com/projects/python/

I'd be cool to implement this as a mode hook but I haven't found a
clean, simple way to do this yet. So, patch it is.

--
|| Preston Landers <mi...@my-deja.com> ||
|| http://askpreston.com ||


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.

Barry A. Warsaw

unread,
Jul 7, 1999, 3:00:00 AM7/7/99
to mil...@uiuc.edu

>>>>> "MAM" == M A Miller <mil...@nialas.npl.uiuc.edu> writes:

MAM> Does anyone have a tweak for python-mode.el that will
MAM> highlight occurrences of self and self.?

You could probably add "self" to python-font-lock-keywords. I'm not
entirely sure this is a good idea since self is just a convention, but
if a lot of people would like to see this, I might consider adding it.

-Barry

Preston Landers

unread,
Jul 7, 1999, 3:00:00 AM7/7/99
to
In article <14211.28251....@anthem.cnri.reston.va.us>,

bwa...@cnri.reston.va.us (Barry A. Warsaw) wrote:

> You could probably add "self" to python-font-lock-keywords. I'm not
> entirely sure this is a good idea since self is just a convention, but
> if a lot of people would like to see this, I might consider adding it.

Well, even though self is a convention, its use is 'strongly encouraged'
and I don't think anybody would be terribly confused by Emacs
highlighting it. Maybe if this was added to python-mode it could be
optional.

My personal opinion is that "self" is much more 'like' a type than a
keyword (like if, elif, for, and so on.) I decided to color it like a
class declaration.

I inserted these lines into my python-mode.el at the appropriate place:

;; also color "self" as a 'type'
'("\\b\\(self\\)[ .,]?"
1 font-lock-type-face)

Sjoerd Mullender <sjoerd.m...@oratrix.com> suggests adding this to
your .emacs instead:

(add-to-list 'after-load-alist
(cons "python-mode"
'((add-to-list (quote python-font-lock-keywords)
(quote ("\\b\\(self\\)[ .,]?"
1 font-lock-type-face))))))

which is a slightly more clever way of doing it. I'm not a terribly
experienced Emacs hacker.

M.A.Miller

unread,
Jul 7, 1999, 3:00:00 AM7/7/99
to
>>>>> "BAW" == Barry A Warsaw <bwa...@cnri.reston.va.us> writes:

> I'm not entirely sure this is a good idea since self is
> just a convention, but if a lot of people would like to see
> this, I might consider adding it.

You could add a defcustom variable for people who use something
other than 'self'?

Mike

0 new messages