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

Inheriting the @ sign from Ruby

1 view
Skip to first unread message

Roy Katz

unread,
Dec 12, 2000, 1:44:16 AM12/12/00
to
Hello,

I was reading a Dr. Dobb's recently and it mentioned that Ruby uses the @
symbol to denote instance members of a class. This appeals to me because
I can comprehend it faster than seeing 'self' pasted in front of a
name, especially when the statement is buried in dense code.

Why not bind @ to the first argument of method definitions? Consider:


class X:

def __init__( self, x ):

@bind(x) # binds to 'self', because
# 'self' is the first argument to __init__

def bind(myself, x):
@x = x # equivalent to myself.x

What faults or strengths do you see with this?


Roey

Michael Hudson

unread,
Dec 12, 2000, 4:29:46 AM12/12/00
to
Roy Katz <ka...@Glue.umd.edu> writes:

> What faults or strengths do you see with this?

It hasn't got a hope in hell! The language is incredibly unlikely to
change this much, I think.

Also, I think it looks horrible, but that could just be me.

Cheers,
M.

--
31. Simplicity does not precede complexity, but follows it.
-- Alan Perlis, http://www.cs.yale.edu/homes/perlis-alan/quotes.html

Fredrik Lundh

unread,
Dec 12, 2000, 4:36:29 AM12/12/00
to
Michael Hudson wrote:
> Also, I think it looks horrible, but that could just be me.

nope.

</F>

Alex Martelli

unread,
Dec 12, 2000, 5:38:07 AM12/12/00
to
"Roy Katz" <ka...@Glue.umd.edu> wrote in message
news:Pine.GSO.4.21.00121...@y.glue.umd.edu...

>
> I was reading a Dr. Dobb's recently and it mentioned that Ruby uses the @
> symbol to denote instance members of a class. This appeals to me because
> I can comprehend it faster than seeing 'self' pasted in front of a
> name, especially when the statement is buried in dense code.

'self' is not "pasted in front of a name" -- 'self' is an object,
and it is used with perfectly regular syntax for object access.

Thus, there is no special-case syntax needed: the regular syntax,
which you need anyway for general cases, takes care of everything
in the special-case as well.


> Why not bind @ to the first argument of method definitions? Consider:
>
>
> class X:
>
> def __init__( self, x ):
>
> @bind(x) # binds to 'self', because
> # 'self' is the first argument to __init__

If you called
someotherobject.bind(x)
you WOULD know what that does, right? Call method 'bind' on
that object with 'x' as an argument.

Therefore,
self.bind(x)
does exactly the same thing, simply and predictably -- the
object on which 'bind' is called being, unsurprisingly,
the one named 'self'.

So, you would like '@identifier' to be a special-case
syntax meaning exactly the same as 'self.identifier' (if
the first argument, as per normal convention, is named
'self').


> def bind(myself, x):
> @x = x # equivalent to myself.x

The violation of the convention (using 'myself' instead
of 'self' as the name of the first argument) is not
remedied by the '@' kludge, of course. Whenever a use
of 'self' is desired, that cannot be brought to the
attribute-access syntax of self.whatever (passing
'self' as an argument to getattr, or to a base-class
version of a method, etc, etc), such a violation of
normal expectations will make your code harder to read
and understand by any maintainers.

I'd much rather have a lint-like checking that the
argument expected to be named self is in fact thus
named, with a warning when it isn't.


> What faults or strengths do you see with this?

I see no strength in this supplementary syntax form
offering a second, different way to express what can
be perfectly well expressed explicitly today.

I see it as a fault that all this does is offer a
second, different way to express what can be perfectly
well expressed explicitly today.

It would also be a (small) step along the road of
turning the currently crystal-clear syntax of Python
into that morass of special-purpose, ad-hoc, 'convenient'
kludges that make certain other languages' typical
programs look so peculiarly similar to line noise.


Alex

Roy Katz

unread,
Dec 12, 2000, 10:50:46 AM12/12/00
to
On Tue, 12 Dec 2000, Alex Martelli wrote:

> 'self' is not "pasted in front of a name" -- 'self' is an object,
> and it is used with perfectly regular syntax for object access.

Yes, we understand this. Passing 'self' (or whatever people choose to
call it) to an instance method is automatic upon invocation, and manual
for anything else. So we have:

Class X:
def __init__( self, c ):
@c = c # @c binds to 'self'.c
def example( self ): X.__init__( self )
def same_example( self ): X.__init__( self )
def another_example( myself, y ): @x = y # binds to 'myself'.y

To me, grammatically and practically, self *is* pasted in as the first
argument. I'm bringing up a grammatical question. My question was
whether or not the shorthand was practical.

> So, you would like '@identifier' to be a special-case
> syntax meaning exactly the same as 'self.identifier' (if
> the first argument, as per normal convention, is named
> 'self').

I would like the @identifier to denote <self-object>.identifier, where
<self-object> is the first parameter to a method. Regardless of whether it
is 'self' or 'myself'; the 'def bind(myself, x)' was just an example.


> such a violation of
> normal expectations will make your code harder to read
> and understand by any maintainers.

Why should there be any violation if all instance identifiers are labelled
with a @? To be honest, I believe that the @identifier convention would
decrease the number of variant programming styles. We all want that
'self' be used (instead of any other name). Fine! the @identifier
scheme would at least reduce this, then. You wouldn't see 'myself' (or
some other deviant) pasted in front of every instance variable; you'd
see a common @ sign. So for reading someone else's code, that's a good
thing.

> > What faults or strengths do you see with this?
>
> I see no strength in this supplementary syntax form
> offering a second, different way to express what can
> be perfectly well expressed explicitly today.

shorthand??

>
> I see it as a fault that all this does is offer a
> second, different way to express what can be perfectly
> well expressed explicitly today.

Save for being able to call the first parameter of a method whatever you
like, wouldn't this reduce the number of programming conventions?

> It would also be a (small) step along the road of

I disagree; Like I mentioned above, this would enforce
standardization.

> turning the currently crystal-clear syntax of Python
> into that morass of special-purpose, ad-hoc, 'convenient'
> kludges that make certain other languages' typical
> programs look so peculiarly similar to line noise.

Python's language is not crystal-clear, imho. If we're so tough on
perl for having a kludgy interface, why do we have {} for
defining dictionaries instead of [ key:value ]? Why do we have to
explain to new Python programmers how the label-value system Python uses
is different than traditional call-by-reference and
call-by-value? (I've been programming in Python for three years now
and I understand only that passing an int or float is call-by-value,
otherwise it is call-by-reference. At the risk of naivete, I would
like a simple & referencing operator so that I can explicitly,
finally, have control over this.) When would I ever use print>> ?
Isn't there a less-ugly way of generating a raw string, instead of placing
an 'r' in front of it?

Good that you mentioned that the language is deteriorating. IMHO, from
the above, it's seemed like this from the start. (It's still my favorite
language).


But that's just my opinion.

Roey.

Mikael Olofsson

unread,
Dec 12, 2000, 11:17:46 AM12/12/00
to

On 12-Dec-00 Roy Katz wrote:
> shorthand??

If you want a shorthand, why not just do

Class X:
def __init__( I, c ):
I.c = c

It is substantially shorter than self. and myself., and only one
character longer than your @-expression, with the advantage that
you can use it at once without any changes to Python itself.

And-I-think-that-@var-is-ugly-ly y'rs

/Mikael

-----------------------------------------------------------------------
E-Mail: Mikael Olofsson <mik...@isy.liu.se>
WWW: http://www.dtr.isy.liu.se/dtr/staff/mikael
Phone: +46 - (0)13 - 28 1343
Telefax: +46 - (0)13 - 28 1339
Date: 12-Dec-00
Time: 17:11:13

/"\
\ / ASCII Ribbon Campaign
X Against HTML Mail
/ \

This message was sent by XF-Mail.
-----------------------------------------------------------------------

Fredrik Lundh

unread,
Dec 12, 2000, 11:26:28 AM12/12/00
to
Roy Katz wrote:
> Why do we have to explain to new Python programmers how the
> label-value system Python uses is different than traditional call-by-
> reference and call-by-value?

Do we? Of course there are people who don't understand that
different languages do things in different ways, but they're not
that common.

The real problem is that many Python tutorials fail to explain
how things work (or hide it somewhere in the exercises), but
that's not really Guido's fault...

> (I've been programming in Python for three years now and I
> understand only that passing an int or float is call-by-value,
> otherwise it is call-by-reference.

Which means that you don't understand how it works...

(Hint: Everything is a reference to an object. Variables are
named references, not actual objects. Some objects can be
modified in place. Some cannot be modified. That's all)

</F>

<!-- (the eff-bot guide to) the standard python library:
http://www.pythonware.com/people/fredrik/librarybook.htm
-->


Roy Katz

unread,
Dec 12, 2000, 11:46:48 AM12/12/00
to
On Tue, 12 Dec 2000, Fredrik Lundh wrote:

> The real problem is that many Python tutorials fail to explain
> how things work (or hide it somewhere in the exercises), but
> that's not really Guido's fault...

Tough for the new Python programmer, then. It's nt fair to them.

> (Hint: Everything is a reference to an object. Variables are
> named references, not actual objects. Some objects can be
> modified in place. Some cannot be modified. That's all)

Okay! tell me, which are the objects which cannot be modified in place? I
assume these are int's, long's, float's, etc. Strings, lists, objects and
dictionaries are call-by-reference. Pardon my choice of diction, but I am
against inventing new terminiologies (modified-in-place??).

I want to know where this is documented. Specifically, where is the
dichotomy of ints/longs/floats vs. objects/strings/lists/dictionaries.

While I'm brainstorming with Python grammar changes, what about a real &
operator. No more of this hokey is-it-modifiable-in-place-or-not
business. Explicit control is important.


Thank you for enlightening me!


Roey

Erik Max Francis

unread,
Dec 12, 2000, 11:56:51 AM12/12/00
to
Roy Katz wrote:

> I disagree; Like I mentioned above, this would enforce
> standardization.

It wouldn't enforce anything, since programmers wouldn't be mandated to
use it. Programmers who didn't want to use the @ shorthand could still
call the `self' argument anything they liked.

To be honest I have seen very little variation in the name of the `self'
argument, and I doubt it would be a huge problem to decipher someone
else's code who used, say, `this' instead. I don't think it's a serious
problem. I don't think the @ shorthand is a bad idea, but at the same
time all it would do is make Python code more obfuscated, start
arguments about whether it was a good idea in the first place, and
unless mandated (which would _really_ piss people off) wouldn't
accomplish the goals it was set out to do.

> Python's language is not crystal-clear, imho.

I don't see how making it more obfuscated would help that.

> If we're so tough on
> perl for having a kludgy interface, why do we have {} for
> defining dictionaries instead of [ key:value ]?

Makes perfect sense, actually -- you have tuples, lists, and
dictionaries, and each are set off with different punctuation to make it
clear to everyone (including the interpreter) what type they are.

> (I've been programming in Python for three years now
> and I understand only that passing an int or float is call-by-value,
> otherwise it is call-by-reference. At the risk of naivete, I would
> like a simple & referencing operator so that I can explicitly,
> finally, have control over this.)

This is actually something I wish had been done explicitly as well; this
is one of the only areas of Python that I found truly irregular and
strange. It would have been nice to either have pass-by-value be the
default and have an explicit operator for referencing, or vice versa
(doesn't matter to me which one, as long as it's consistent;
pass-by-value as the default makes a little more sense). Alas, it is a
little too late for that.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/ \ If I had another face, do you think I'd wear this one?
\__/ Abraham Lincoln
Official Omega page / http://www.alcyone.com/max/projects/omega/
The official distribution page for the popular Roguelike, Omega.

Simon B.

unread,
Dec 12, 2000, 11:50:16 AM12/12/00
to
In article <Pine.GSO.4.21.001212...@y.glue.umd.edu>,
Roy Katz <ka...@Glue.umd.edu> wrote:

> I've been programming in Python for three years now
> and I understand only that passing an int or float is call-by-value,
> otherwise it is call-by-reference

Isn't that Java? It *certainly* isn't Python - *everything* is by
reference in python. Unless I'm *really* confused...

--
Simon Brunning
Nothing simple is ever easy. - Jim Becker


Sent via Deja.com
http://www.deja.com/

Simon B.

unread,
Dec 12, 2000, 12:04:54 PM12/12/00
to

> From: Roy Katz [SMTP:ka...@Glue.umd.edu]

> Okay! tell me, which are the objects which cannot be modified in
place? I
> assume these are int's, long's, float's, etc. Strings, lists,
objects and
> dictionaries are call-by-reference. Pardon my choice of diction, but
I am
> against inventing new terminiologies (modified-in-place??).

The correct terminology is mutable (for objects which can be modified in
place), and immutable (for objects which cannot). See
<http://www.python.org/doc/current/ref/objects.html>.

> I want to know where this is documented. Specifically, where is the
> dichotomy of ints/longs/floats vs.
objects/strings/lists/dictionaries.

The built-in types are documented here -
<http://www.python.org/doc/current/ref/types.html> - including whether
or
not they are mutable.

> While I'm brainstorming with Python grammar changes, what about a
real &
> operator. No more of this hokey is-it-modifiable-in-place-or-not
> business. Explicit control is important.

Ugh.

Cheers,
Simon Brunning
TriSystems Ltd.
sbru...@trisystems.co.uk

Bjorn Pettersen

unread,
Dec 12, 2000, 12:35:07 PM12/12/00
to
Roy Katz wrote:

Besides being visually unpleasant, it wouldn't work for the following code:

class Outer:
class Inner:
def __init__(self, x):
self.x = x
def __init__(self, x):
self.x = x

and various other variations (like defining a class inside a method etc.)
While these cases aren't particularly common in current Python code, they
might be when/if PEP-227 (http://python.sourceforge.net/peps/pep-0227.html)
makes it into the next version (discussion on whether functions are first
class objects in Python can now comense <wink>).

-- bjorn


Fredrik Lundh

unread,
Dec 12, 2000, 12:37:58 PM12/12/00
to
Roy Katz wrote:
> > The real problem is that many Python tutorials fail to explain
> > how things work (or hide it somewhere in the exercises), but
> > that's not really Guido's fault...
>
> Tough for the new Python programmer, then. It's nt fair to them.

Sorry, but I don't understand that comment. I've done a lot
of Python training lately, and nobody has had any problems
whatsoever understanding this.

(well, Lisp and Smalltalk programmers seem to have trouble
understanding why anyone would do things in any other way...)

> > (Hint: Everything is a reference to an object. Variables are
> > named references, not actual objects. Some objects can be
> > modified in place. Some cannot be modified. That's all)
>
> Okay! tell me, which are the objects which cannot be modified in place? I
> assume these are int's, long's, float's, etc. Strings, lists, objects and
> dictionaries are call-by-reference. Pardon my choice of diction, but I am
> against inventing new terminiologies (modified-in-place??).

Sigh. The problem is that you keep using terms that mean
something for you, whether or not they apply to the current
situation.

If you want to learn something new, you have to stop doing
that.

Reset your brain.

Python doesn't use call-by-value, and it doesn't use call-by-
reference either (at least not given your definitions of those
terms).

Realize that there are more than one way to do it.

Here's how it's done in Python:

:::

All Python objects has the following:

-- some content
-- an unique identity (a integer, returned by id(x))
-- a type (returned by type(x))

You cannot change the identity.

You cannot change the type.

Some objects allow you to change the *content* (without
changing the identity or the type, that is).

Some objects don't allow you to change the content
(more below).

The type is represented by a type object, which knows
more about objects of this type (how many bytes of
memory they usually occupy, what methods they have,
etc).

:::

Objects may also have:

-- zero or more methods (provided by the type object)
-- zero or more names

Some objects have methods that allow you to change the
contents of the object (modify it in place, that is).

Some objects only have methods that allow you to access
the contents, not change it.

Some objects don't have any methods at all.

Even if they have methods, you can never change the type,
nor the identity.

Things like attribute assignment and item references are just
syntactic sugar (more below).

:::

The names are a bit different -- they're not really properties
of the object, and the object itself doesn't know what it's
called.

An object can have any number of names, or no name at all.

Names live in namespaces (such as a module namespace, an
instance namespace, a function's local namespace).

Namespaces are collections of (name, object reference) pairs.
(Or in other words, they're dictionaries).

When you call a function or a method, it's namespace is
initialized with the arguments you call it with (the names
are taken from the function's argument list, the objects
are those you pass in).

:::

Assignment modify namespaces, not objects.

In other words,

name = 10

means that you're adding (or replacing) the name "name" in
your local namespace, and making it refer to an integer object
containing the value 10.

name = 10
name = 20

means that you're first adding the name "name" to the local
namespace, and making it refer to an integer object containing
the value 10. You're then replacing the name, making it point
to an integer object containing the value 20. The original "10"
object isn't affected by this operation, and it doesn't care.

In contrast, if you do:

name = []
name.append(1)

you're first adding the name "name" to the local namespace,
making it refer to an empty list object. You're then calling a
method on that object, telling it to add an integer object to
itself.

Things like "name.attr" and "name[index]" are just syntactic
sugar. The first corresponds to __setattr__/__getattr__, the
second to __setitem__/__getitem__, depending on which side
of the assignment operator they appear).

That's all.

:::

> I want to know where this is documented. Specifically, where is the
> dichotomy of ints/longs/floats vs. objects/strings/lists/dictionaries.

There is no dichotomy. Some objects have methods that let
you modify them, some don't. Read the language reference.
If you stop thinking in C terms, you may understand what it's
talking about.

> While I'm brainstorming with Python grammar changes, what about a real &
> operator. No more of this hokey is-it-modifiable-in-place-or-not
> business. Explicit control is important.

As I just explained, Python doesn't work that way.

</F>


Remco Gerlich

unread,
Dec 12, 2000, 12:45:45 PM12/12/00
to
Roy Katz <ka...@Glue.umd.edu> wrote in comp.lang.python:

> On Tue, 12 Dec 2000, Fredrik Lundh wrote:
>
> > The real problem is that many Python tutorials fail to explain
> > how things work (or hide it somewhere in the exercises), but
> > that's not really Guido's fault...
>
> Tough for the new Python programmer, then. It's nt fair to them.
>
> > (Hint: Everything is a reference to an object. Variables are
> > named references, not actual objects. Some objects can be
> > modified in place. Some cannot be modified. That's all)
>
> Okay! tell me, which are the objects which cannot be modified in place?

Integers, longs, complex numbers, strings, functions, tuples, types, floats
and None are immutable. Most of these are obvious; the number 3 is the
number 3, why would you change that?!

Lists, classes, instances, dictionaries and modules are mutable.

Did I miss any?

So there are only three mutable things: lists, dictionaries, and namespaces.

Anyway, the important ones of these are in any Python book. You sure you've
been programming Python for three years?

> assume these are int's, long's, float's, etc. Strings, lists, objects and
> dictionaries are call-by-reference. Pardon my choice of diction, but I am
> against inventing new terminiologies (modified-in-place??).

Mutable and immutable. And *everything* is by reference, including
assignment. No new terminology here.

> I want to know where this is documented. Specifically, where is the
> dichotomy of ints/longs/floats vs. objects/strings/lists/dictionaries.

Strings are not mutable.

There is no real dichotomy here. Some types have methods that can change
the type, other types don't. Some types are namespaces (modules, classes
and instances), and they can be changed.

> While I'm brainstorming with Python grammar changes,

Not a very useful idea 10 years after the language was released, but
whatever...

--
Remco Gerlich

Fredrik Lundh

unread,
Dec 12, 2000, 12:53:23 PM12/12/00
to
Simon wrote:
> Pardon my choice of diction, but I am against inventing
> new terminiologies (modified-in-place??).
>
> The correct terminology is mutable (for objects which can be modified in
> place), and immutable (for objects which cannot).

Well, I doubt anyone who doesn't understand the meaning
of "modifying something in place" understands exactly what
"mutable" means...

(especially since the latter is as likely to mean "may change
itself" as "may be changed" ;-)

But maybe I should use "in situ" to make it sound a bit more
formal...

</F>


Fredrik Lundh

unread,
Dec 12, 2000, 12:56:17 PM12/12/00
to
Remco Gerlich wrote:
> There is no real dichotomy here. Some types have methods that can change
> the type, other types don't.

careful: you meant "can change the contents of objects of that type"

(but you already know that, of course).

</F>


Erik Max Francis

unread,
Dec 12, 2000, 12:55:31 PM12/12/00
to
"Simon B." wrote:

> Isn't that Java? It *certainly* isn't Python - *everything* is by
> reference in python. Unless I'm *really* confused...

You're right, but for the immutable types, for all intents and purposes
passing by reference and passing by value are essentially the same
thing, because unless you're playing with the is operator, someone else
can't change the immutable object that you're pointing to, so it acts
very much like pass-by-value.

I presume (and my previous post was predicated on this) that the
original poster knew what he was talking about and was indeed just
analyzing Python's behavior from a high-level, C-like approach, talking
about pass-by-value for the immutables and pass-by-reference for
anything else for the sake of discussion.

I, too, wish that there were some more fundamental, builtin operator for
implementing shallow and deep copying that worked for all types; given
that everything in Python is passed by reference, I'm surprised that a
fundamental builtin (type-inspecific) operator for doing copies didn't
make it into the language very early on.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ An undevout astronomer is mad.
\__/ Edward Young
Alcyone Systems / http://www.alcyone.com/
Alcyone Systems, San Jose, California.

Fredrik Lundh

unread,
Dec 12, 2000, 1:10:05 PM12/12/00
to
Simon wrote:
> Isn't that Java? It *certainly* isn't Python - *everything* is by
> reference in python. Unless I'm *really* confused...

using Roy's definitions, "call by reference" means that you
can change whatever the reference points to.

that's not true in Python.

better avoid the terms completely, since Python's model isn't
neither strict call-by-value (arguments aren't copied), nor strict
call-by-reference (not all arguments can be modified in place).

</F>


Alex Martelli

unread,
Dec 12, 2000, 12:26:38 PM12/12/00
to
"Roy Katz" <ka...@Glue.umd.edu> wrote in message
news:Pine.GSO.4.21.001212...@y.glue.umd.edu...

> On Tue, 12 Dec 2000, Alex Martelli wrote:
>
> > 'self' is not "pasted in front of a name" -- 'self' is an object,
> > and it is used with perfectly regular syntax for object access.
>
> Yes, we understand this. Passing 'self' (or whatever people choose to
> call it) to an instance method is automatic upon invocation, and manual
> for anything else. So we have:

I'm not sure what you mean in this context by 'invocation'. Consider:

foo = FooClass()

f = foo.method
g = FooClass.method

f('pap')
g(foo, 'pap')

The passing of the first-argument object is automatic "upon
invocation" of a BOUND-method-object; it's NON-automatic
("manual", if you wish) "upon invocation" of an UNBOUND-
method-object. (Where in each case I am taking 'invocation'
as a synonym of 'call').

So, I'm not clear what exact distinction you're trying to
draw here by saying 'upon invocation' as against "anything
else". Aren't the calls of f and g 'invocations' both?
Or do you distinguish as 'invocations' some of the calls
to a callable object, depending on said object's nature?
If the latter, then I've never heard of such a distinction.


> To me, grammatically and practically, self *is* pasted in as the first
> argument. I'm bringing up a grammatical question. My question was
> whether or not the shorthand was practical.

When you call a bound-method, the first argument can be,
I guess, said to be 'pasted' (strange terminology!). But
that has nothing to do with the USE of the first (or
other) arguments in the body of functions that receive
them. Such arguments are used with uniform syntax, no
matter whether they're the first, or not -- just the
same, identical syntax as that available for ANY use
of ANY other object.

Your 'shorthand' singles out ONE subcase (attribute
access via dot-notation) out of all, for ONE object
(the one received by a method as its first argument)
out of all, introducing an alternative way of
expressing that single, specific combination out of
all the huge variety; in other words, it introduces
a special-case, ad-hoc irregularity in a perfectly
simple and regular scheme. This is one of the reasons
I find it a terrible idea (and from other responses
I've read on this thread, it seems to be a widespread
opinion).


> > So, you would like '@identifier' to be a special-case
> > syntax meaning exactly the same as 'self.identifier' (if
> > the first argument, as per normal convention, is named
> > 'self').
>
> I would like the @identifier to denote <self-object>.identifier, where
> <self-object> is the first parameter to a method. Regardless of whether it
> is 'self' or 'myself'; the 'def bind(myself, x)' was just an example.

If the singled-out argument is not named 'self', as it normally
is, readability will suffer anyway, I keep asserting. The
'shorthand' will do nothing substantial to help, and if it
encourages such breaches of convention it will positively
hinder, the current uniformity of usage.


> > such a violation of
> > normal expectations will make your code harder to read
> > and understand by any maintainers.
>
> Why should there be any violation if all instance identifiers are labelled
> with a @? To be honest, I believe that the @identifier convention would
> decrease the number of variant programming styles. We all want that

How can it possibly DECREASE them? It would introduce ONE MORE way
to express the SAME, IDENTICAL thing, and thus it can only INCREASE
variability of expression, as some code says '@goo' while other
code keeps saying 'self.goo' instead.

> 'self' be used (instead of any other name). Fine! the @identifier
> scheme would at least reduce this, then. You wouldn't see 'myself' (or
> some other deviant) pasted in front of every instance variable; you'd
> see a common @ sign. So for reading someone else's code, that's a good
> thing.

Absolutely NOT. If lulled by the @-signs in most places, I'm LESS
likely to notice that the code's author has wantonly called the
self-object 'myself', while 'self', if it exists at all, may refer
to some other object (say a global). So when the time comes that
the self-object is used, or should be used, e.g. in calling a base
class method, or getattr, etc, etc, it becomes MORE likely, not
less, than the confusion will prove damaging.

*EXPLICIT IS BETTER THAN IMPLICIT* -- a very important guiding
principle of Python programming.
localvar=self.goo
is more explicit than
localvar=@goo
in that, if, for example, I need to change this for maintenance
to
localvar=getattr(self,'goo',None)
(a reasonably frequent occurrence), I don't have to unravel the
implicitness -- I *KNOW*, because I read it *right there*, the
name of the object that I need to pass to getattr (etc etc).


> > > What faults or strengths do you see with this?
> >
> > I see no strength in this supplementary syntax form
> > offering a second, different way to express what can
> > be perfectly well expressed explicitly today.
>
> shorthand??

Is saving 4 characters, '@' vs 'self.', so important as
to warrant the 'fork' in coding styles, the redundancy
itself, etc? Not to me. Most Pythonistas seem to be
even more minimalist, begrudging such new constructs as
list-comprehensions (which save a lot more than 4 chars,
and even have some 'conceptual' advantages).


> > I see it as a fault that all this does is offer a
> > second, different way to express what can be perfectly
> > well expressed explicitly today.
>
> Save for being able to call the first parameter of a method whatever you
> like, wouldn't this reduce the number of programming conventions?

Maybe there's an implication I find it hard to swallow: would
you want to make 'self.foo' ILLEGAL, breaking _all_ existing
Python code? Because, if not, it appears to be obvious that
some code will keep saying 'self.foo' while other says '@foo',
and I really don't understand how you can possibly claim the
obviously-false 'reduction' in 'number of conventions'...

> > It would also be a (small) step along the road of
>
> I disagree; Like I mentioned above, this would enforce
> standardization.

...or the 'enforcement of standardization', either.


> > turning the currently crystal-clear syntax of Python
> > into that morass of special-purpose, ad-hoc, 'convenient'
> > kludges that make certain other languages' typical
> > programs look so peculiarly similar to line noise.
>
> Python's language is not crystal-clear, imho. If we're so tough on

I was (and am) claiming crystal-clear *SYNTAX*.

> perl for having a kludgy interface, why do we have {} for
> defining dictionaries instead of [ key:value ]?

Because the Python object denoted by the syntax:
[ whatever_you_want ]
is *ALWAYS* a list, and a dictionary is not a list. Breaking
this 'always' would hardly enhance language-clarity!


> Why do we have to
> explain to new Python programmers how the label-value system Python uses
> is different than traditional call-by-reference and
> call-by-value?

Sez who? People I've seen with Python as their first
language, and people I've seen coming from Java (which
has exactly the same argument-passing mechanism), seem
to have no trouble (there are many other languages which
work this way, but I have not observed Python users who
started out in any of those other languages). I'm not
sure what you mean by 'label-value', but the semantics
of argument-passing, in Python, is exactly that of the
'assignment' operator, which simplifies the exposition
of both (the great uniformity of the Python treatment of
references is quite beneficial).

When passing any argument, the receiving function always
gets a reference to that argument, usable exactly as any
other reference to the same object would be (e.g., any
variable bound to that object, any list-item bound to
that object, any dictionary-entry bound to that object),
and so on. If the object thus 'passed' is immutable, it
cannot be changed through the reference the function has;
if it offers methods by which it can be changed, those
methods may be called -- exactly as would be the case if
the reference was a list-item, dictionary-entry, whatever.

Re-binding the reference only affects the reference, not
the previously-bound object, nor any other reference, for
any of these kinds of references (arguments just as well
as any other). You can't get any simpler, more uniform,
or clearer, than this. (Calling re-binding 'assignment'
*MAY* be slightly-confusing terminology to some people).

People whose only language exposure, previous to Python
(or Java, etc) was to languages whose argument-passing
mechanisms differed greatly may be confused, I guess. But
the fact that Python (or Java) differ on this from other
languages hardly touches on their _clarity_. Actually,
the issue is more likely to be with '=', SO-CALLED
'assignment' in Java or Python, ACTUAL assignment in
Fortran, C, C++. The '=', in Fortran, C, or C++, will
normally "copy bits from one place to another", i.e.,
'assign' stuff. In Java or Python, '=' _rebinds the
reference on its left-hand side so it now refers to
the result of the expression on its right-hand side_
(if any bits are copied to perform this, it will be the
few bits the language internally uses to keep track
for each reference of the issue 'to what object does
this reference refer right now' -- language-internal
issues of small import to its conceptual-model).


> (I've been programming in Python for three years now
> and I understand only that passing an int or float is call-by-value,
> otherwise it is call-by-reference.

Wrong, in terms of those languages where call-by-value
and call-by-reference have meaning (and, not coincidentally,
'=' or equivalent similar syntax DOES perform assignment).

Take C++, for example:

Foo foo(1);
Foo bar(2);

void afun(Foo& a, Foo& b)
{
Foo temp(0);
temp = a;
a = b;
b = temp;
}

afun(foo, bar);


Now THIS is call-by-reference: the assignment operators
which afun calls on its formal arguments a and b affect
the actual arguments passed, foo and bar. Unless class
Foo redefines the assignment-operator operator= to
something VERY peculiar, this sequence will leave the
global variables 'foo' and 'bar' ``swapped'' in terms
of contents after the call to afun.

In Python, on the other hand:

foo = Foo(1)
bar = Foo(2)

def afun(a, b):
temp = a
a = b
b = temp

afun(foo, bar)

all the *re-bindings* (SO-CALLED 'assignments', but
not really assignments!) that THIS afun performs on
its LOCAL VARIABLES temp, a, and b, have ABSOLUTELY
NO EFFECT WHATSOEVER on the actual-arguments foo
and bar: they are absolutely unchanged and pristine
after the call to afun, referring to exactly the
same objects to which they referred before it.

So, modeling Python's argument-passing as "by reference"
in this case (although it's an "otherwise") is simply
wrong, in terms of (for example) C++'s references (but
Visual Basic, Fortran, and other languages which DO
have pass-by-reference and actual assignment work much
like C++ does here).


> At the risk of naivete, I would
> like a simple & referencing operator so that I can explicitly,
> finally, have control over this.)

You have full control, and clarity, NOW -- if you take
the trouble to understand a little bit better how Python
really works, rather than proposing changes to it.

> When would I ever use print>> ?

In my humble opinion, never; I consider it a hateful
kludge, and its insertion in the Python language the
worst single thing that ever happened to Python in
its (almost) 10-years history.

OK, so, I guess even I (and I know few people prouder
than me) can allow the BDFL *one* terrible mistake
per 10 years or so...:-).

> Isn't there a less-ugly way of generating a raw string, instead of placing
> an 'r' in front of it?

Not that I know, though other languages have tried all
sorts of slight syntax-sugar variations (using " to
delimit non-raw, and ' to delimit raw-strings, for
example). The r-decoration seems just fine to me.


> Good that you mentioned that the language is deteriorating. IMHO, from

I have said no such thing. I said Python WOULD deteriorate
IF the @ special-case syntax was added to it (the only
deterioration I ever saw happen to Python was the recent
addition of the >> special-case syntax for print).


> the above, it's seemed like this from the start. (It's still my favorite
> language).

I'm really surprised that you have not taken the trouble
to grasp the references/objects semantics of Python, and
how it works uniformly and smoothly (in argument-passing
just as everywhere else), in 3 years, for what you say
it's your favourite language.

It's really a very, VERY simple idea -- though I hardly
ever see it explained as explicitly as it deserves to be,
and in fact the common idea of calling '=' "assignment"
(used in the Python docs, too) does its own little part
to obscure it.


Alex

Erno Kuusela

unread,
Dec 12, 2000, 1:39:05 PM12/12/00
to
In article <slrn93cotl....@pino.selwerd.nl>,
scar...@pino.selwerd.nl (Remco Gerlich) writes:

| Integers, longs, complex numbers, strings, functions, tuples, types, floats
| and None are immutable. Most of these are obvious; the number 3 is the
| number 3, why would you change that?!

it is easy to think that when you know how things work in python.
but, you could just as easily say, "a list containing the numbers 1, 2 and
3 is a list of 1, 2 and 3, why would you change that?!"
mutable integer or string objects are certainly not an impossible idea.

-- erno

Daniel Wood

unread,
Dec 12, 2000, 2:35:04 PM12/12/00
to
I'm glad this discussion is happening because I've been learning
python and I'm worried that the bloom is coming off of our romance.
Perhaps if I can be more understanding, our relationship can survive
. . .

scar...@pino.selwerd.nl (Remco Gerlich) writes:

> Integers, longs, complex numbers, strings, functions, tuples, types, floats
> and None are immutable. Most of these are obvious; the number 3 is the
> number 3, why would you change that?!

Here is what I wanted to do. I have some random parameters, lambda
and beta. My calculation uses them like so:

plot( lambda, beta )

I'm using pygtk as a widget set. I have some sliders. I wanted to
make one of the sliders control lambda and one control beta. The
control should be scaled by some parameter etc, etc. Now I could have
a function

def lambdaCB( val ):
global lambda
lambda = val / constant

but instead I thought that I would have a simple class

class ScaleCB:
def __init__( self, variable, scale ):
self.variable = variable
self.scale = scale

def __call__( self, val )
self.variable = val / self.scale

(then, I can do lots of parameters with nice simple code instead of
bunches of stupid helper functions.

This obviously didn't work.

I *think* that the "pythonic" sol'n appears to be lambda = [ value ]
or some such. Clearly, one person's hack is another person's idiom,
but I can't convince myself that this doesn't suck. It seems like
what I want is a better idiom for a "mutable integer". I guess it
would be something just like an int but with a set method.

(Excessive detail here: I'm using swig and in fact these variables are
part of swig's cvar interface. The cvar interface appears to use some
sort of __getattr__ and __setattr__ hooks in a very un-pythonic way.
I'm not sure but I *think* that this is because SWIG is trying to
expose mutable floats, ints, etc. It basically binds a NAME
(e.g. cvar.myvar) to a C language thing instead of some sort of object
living in cvar.myvar that corresponds to a C language thing. I
believe that the SWIG notes mentions something about this and
basically SWIG wants you to be able to do "cvar.myvar = 10" and get
the C style effect. This has the sad effect that you can't take the C
language bindings and use them in any way other than with the official
NAME "cvar.etcetc".)

Clues gratefully accepted,
Daniel.

Fredrik Lundh

unread,
Dec 12, 2000, 2:49:21 PM12/12/00
to
Daniel Wood wrote:
> Here is what I wanted to do. I have some random parameters, lambda
> and beta. My calculation uses them like so:
>
> plot( lambda, beta )

lambda is a reserved word, so I doubt that's what you're
doing. Let's call it "spam" instead.

> I'm using pygtk as a widget set. I have some sliders. I wanted to
> make one of the sliders control lambda and one control beta. The
> control should be scaled by some parameter etc, etc. Now I could have
> a function
>
> def lambdaCB( val ):
> global lambda
> lambda = val / constant
>
> but instead I thought that I would have a simple class
>
> class ScaleCB:
> def __init__( self, variable, scale ):
> self.variable = variable
> self.scale = scale
>
> def __call__( self, val )
> self.variable = val / self.scale
>
> (then, I can do lots of parameters with nice simple code instead of
> bunches of stupid helper functions.
>
> This obviously didn't work.

(didn't do what you wanted it to do, at least)

How about this one:

class PlotParams:
def __init__(self):
self.spam = 1
self.beta = 2
def setspam(self, value):
self.spam = value
self.redraw()
def setbeta(self, value):
self.beta = value
self.redraw()
def redraw(self):
plot(self.spam, self.beta)

myplot = PlotParams()

spamScaleWidget.setcallback(myplot.setspam)
betaScaleWidget.setcallback(myplot.setbeta)

> I *think* that the "pythonic" sol'n appears to be lambda = [ value ]
> or some such.

Besides being a syntax error, it doesn't look very Pythonic
to me. If you want to change a named value, the best way
is to make it an attribute of a class.

</F>


Daniel Wood

unread,
Dec 12, 2000, 3:05:52 PM12/12/00
to

"Fredrik Lundh" <fre...@effbot.org> writes:
>
> lambda is a reserved word, so I doubt that's what you're
> doing. Let's call it "spam" instead.

Oops. I was just making up an example for the post and lambda was the
first parameter that came to mind.

> Besides being a syntax error, it doesn't look very Pythonic
> to me. If you want to change a named value, the best way
> is to make it an attribute of a class.

Hmmm, I'm open to the suggestion that I need to rethink my plan at a
larger scale, but isn't a mutable int likely to sometimes be useful?
(Just like a mutable list is sometimes useful.) And if so, is [ 2 ]
the currently favored idiom? (And if so, isn't there something
better?)

Thanks,
Daniel.

Darren New

unread,
Dec 12, 2000, 3:44:00 PM12/12/00
to
Daniel Wood wrote:
> Hmmm, I'm open to the suggestion that I need to rethink my plan at a
> larger scale, but isn't a mutable int likely to sometimes be useful?

No. That's why people invented variables.

Having
x = 2 + 2
print x
result in anything except "4" is probably a *really* bad idea.
AFAIK, only FORTH and really old Fortrans allow this.

--
Darren New / Senior MTS & Free Radical / Invisible Worlds Inc.
San Diego, CA, USA (PST). Cryptokeys on demand.
Personal malapropism generator free with purchase!
Steganography: The manual is hidden in the source code.
Gold mining is only profitable because of the gold found.

Roy Katz

unread,
Dec 12, 2000, 4:19:09 PM12/12/00
to
On Tue, 12 Dec 2000, Fredrik Lundh wrote:


> Sigh. The problem is that you keep using terms that mean
> something for you, whether or not they apply to the current

> situation. [snip]


> If you want to learn something new, you have to stop doing

> that. [snip]


> Here's how it's done in Python:

> [wonderful explanation snipped]


Thank you very much, I understand now more or less how this works.
Furthermore I appreciate your thoughtful, measured, and flame-free tone.


Roey


--------

to everyone else:

Thanks for your responses.
just to clarify something about '@identifier': I'm playing devil's
advocate. So don't see this as an attack. Judging
from the tone of voice in some responses, it seems they took my original
post (which was just a what-if) as some affront to the
language. Ordinarily, So I'm fine either way the discussion swings, as
long as it is constructive.


I do, however, take to heart when people take potshots at me.
If I say I've been programming Python for N years, take it
at face value. It seems to make people feel better
when they come down on someone else's experience. "What, you say you've
been programming for *THREE* years and you *STILL* can't get it??" is pure
ill will. I'm not trying to come off as some hotshot, I was only asking a
question. If you must know why I have had difficulty grasping Python's
labelling system, perhaps it is because I have had 10+ years' C/C++
experience. So that is what I know.

Sometimes you've got to give someone the benefit of the doubt. If s/he
mis-assumes, that's no reason to start letting loose with these kinds of
comments. No doubt someone will append here some line like 'well you
should have read the python docs if you wanted to know
xyz..'. Whatever. If I had found and understood this exact
documentation in the Python docs, I would not have posted the question.


Anyhow, Like I said, thank you all very
much for your responses, I appreciate them. To anyone who still feels
a need to nitpick, go ahead and fix my spelling mistakes. Honestly don't
care anymore; I got what I needed and now I'm done.


Daniel Wood

unread,
Dec 12, 2000, 4:24:05 PM12/12/00
to
2 would not be mutable. Certainly.

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"?)

Thanks,
Daniel.

Aahz Maruch

unread,
Dec 12, 2000, 4:32:30 PM12/12/00
to
In article <r0pwvd5...@black.cs.washington.edu>,

Daniel Wood <dan...@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.
--
--- Aahz (Copyright 2000 by aa...@pobox.com)

Androgynous poly kinky vanilla queer het <*> http://www.rahul.net/aahz/
Hugs and backrubs -- I break Rule 6

What if there were no rhetorical questions? --Aahz

Erno Kuusela

unread,
Dec 12, 2000, 4:48:54 PM12/12/00
to
In article <3A368E11...@san.rr.com>, Darren New
<dn...@san.rr.com> writes:

| Having
| x = 2 + 2
| print x
| result in anything except "4" is probably a *really* bad idea.
| AFAIK, only FORTH and really old Fortrans allow this.

agreed - but this is not something (sane) a mutable integer object
would break.

-- erno

Alex Martelli

unread,
Dec 12, 2000, 3:46:16 PM12/12/00
to
"Daniel Wood" <dan...@cs.washington.edu> wrote in message
news:r0pzoi1...@black.cs.washington.edu...

> I'm glad this discussion is happening because I've been learning
> python and I'm worried that the bloom is coming off of our romance.
> Perhaps if I can be more understanding, our relationship can survive

Understanding can help, and can hardly hinder.


> Here is what I wanted to do. I have some random parameters, lambda
> and beta. My calculation uses them like so:
>
> plot( lambda, beta )

I think lambda is a reserved word, so call it alpha, which sounds
pretty normal anyway:-). But in any case: your 'random
parameters' are *values*; 'lambda' and 'beta' are *names*
(each of which may apply to different values at different
times). OK so far?

Now, your calculation surely uses the _values_ -- the function
named 'plot' will give its own internal, local names to the
_values_ you pass to it, and you don't care about those names.
Right?

Names, incidentally, are nearly always 'attributes' of some
'object' (local-variable-names are the reason for that
'nearly'... due to an optimization, they aren't well modeled
as attributes of any object). They can be accessed as:
object.variablename
or, equivalently:
getattr(object,'variablename')

You may not be aware of this regarding 'global variable
names', because they can _also_ be accessed (in the
right circumstances) as:
variablename
as the module-object's dictionary is 'the global namespace'
of code in that module.


> I'm using pygtk as a widget set. I have some sliders. I wanted to
> make one of the sliders control lambda and one control beta. The

You want user-action events on those sliders to make alpha (and beta)
refer to different values, right?

Ok, to bind a name in an object to a new value, you do:
setattr(object, 'thename', thenewvalue)
[there are other syntaxes that work, but this one is fine].

> control should be scaled by some parameter etc, etc. Now I could have
> a function
>
> def lambdaCB( val ):
> global lambda
> lambda = val / constant

Global variables are most often best avoided, for several different
reasons. Anyway, just like for value-getting, this syntax does
work as an alternative to setattr -- only for the current 'global
namespace', though, i.e., the current module's dictionary.


> but instead I thought that I would have a simple class
>
> class ScaleCB:
> def __init__( self, variable, scale ):
> self.variable = variable
> self.scale = scale
>
> def __call__( self, val )
> self.variable = val / self.scale
>
> (then, I can do lots of parameters with nice simple code instead of
> bunches of stupid helper functions.
>
> This obviously didn't work.

Here, __call__ rebinds the attribute named 'variable' in the
object self. It will work fine if, and only if, that name in
that object is the one you're interested in.

It appears that what you want to rebind, instead, is an
attribute named with whatever string variable is referring
to, in an object that is the global-dictionary of your caller.

Fixing the object in this way is not very friendly, and I
suggest you let the caller pass it in, instead -- it can
pass its own module, or whatever else it likes best
(I'd make it default to _the object itself_ that you're
constructing... seems natural & handy for the caller!).

Then, you can do:

class ScaleCB:

def __init__(self, variableName, scale, object=None):
self._variableName = variableName
self._object = object
if self._object is None:
self._object = self
self._scale = scale

def __call__(self, val)
setattr(self._object, self._variableName, val/self._scale)

It's also possible to use metaprogramming tricks to
find out the object corresponding to the caller's module,
but I would not advise this.


> I *think* that the "pythonic" sol'n appears to be lambda = [ value ]
> or some such. Clearly, one person's hack is another person's idiom,
> but I can't convince myself that this doesn't suck. It seems like
> what I want is a better idiom for a "mutable integer". I guess it
> would be something just like an int but with a set method.

You can do that, if you wish. It may be cleaner than the idea
of 'rebinding a variable in an object at the caller's choice' (IS
certainly sounder than rebinding it in an object fixed to our
own global namespace, it seems to me). It just takes some
patience to implement all of the number-methods in the class
whose instances you want to use as 'mutable integers', if you
want them to be usable 'transparently', "just as if" they really
were integers.

Not sure how this plays with the SWIG issue, sorry -- if the
object in which the name resides doesn't want to play by
Python rules (supporting 'obj.cv=10' and setattr(obj,'cv'10)
as equivalent), then some ad-hoc trick (if any) will have to
be sought. But surely SWIG will document some way for
Python code to set these bindings, or, worst-case, one can
be reverse-engineered from the source it generates...?


Alex

Alex Martelli

unread,
Dec 12, 2000, 3:51:45 PM12/12/00
to
"Daniel Wood" <dan...@cs.washington.edu> wrote in message
news:r0py9xl...@black.cs.washington.edu...
[snip]

> Hmmm, I'm open to the suggestion that I need to rethink my plan at a
> larger scale, but isn't a mutable int likely to sometimes be useful?

Yes. A UserInt equivalent to UserDict and UserList would be
nice to have (a mutable and inheritable integer). All it takes
is some patience to write one, as the number methods are not
few. I wouldn't be surprised if there was one around already...

But I'm not sure how such a hypothetical class would help
you with your SWIG problem.


Alex

Erno Kuusela

unread,
Dec 12, 2000, 4:54:37 PM12/12/00
to
In article <r0pwvd5...@black.cs.washington.edu>, Daniel Wood
<dan...@cs.washington.edu> writes:

| class MutableInt:
[...]

% grep 'class .*Var' Tkinter.py
class Variable:
class StringVar(Variable):
class IntVar(Variable):
class DoubleVar(Variable):
class BooleanVar(Variable):

| My question is: am I confused if I think that this might be useful?

i won't vouch on your unconfusedness, but this might indeed
be useful.

-- erno

[btw, am i the only one in this newsgroup who finds "jeopardy style"
quoting slightly annoying?]

Aahz Maruch

unread,
Dec 12, 2000, 5:11:36 PM12/12/00
to
In article <kupuix7...@lasipalatsi.fi>,

Erno Kuusela <erno...@erno.iki.fi> wrote:
>
>[btw, am i the only one in this newsgroup who finds "jeopardy style"
>quoting slightly annoying?]

Dunno. What's "jeopardy style" quoting? Is that what's often called
"top-posting"?

Fredrik Lundh

unread,
Dec 12, 2000, 5:16:50 PM12/12/00
to
When you see the answer before the question.

Aahz Maruch

unread,
Dec 12, 2000, 5:48:17 PM12/12/00
to
In article <mtxZ5.3611$Kd1.4...@newsb.telia.net>,

Fredrik Lundh <fre...@effbot.org> wrote:
>Aahz wrote:
>>
>> What's "jeopardy style" quoting?
>
>When you see the answer before the question.

Oh, *duh*.

Carel Fellinger

unread,
Dec 12, 2000, 5:50:17 PM12/12/00
to
Daniel Wood <dan...@cs.washington.edu> wrote:

> Hmmm, I'm open to the suggestion that I need to rethink my plan at a
> larger scale, but isn't a mutable int likely to sometimes be useful?
> (Just like a mutable list is sometimes useful.) And if so, is [ 2 ]
> the currently favored idiom? (And if so, isn't there something
> better?)

What about a class? The only thing that is impossible is to set a new
value to its instances with the "instance = value" syntax. But then
neither does "a=1; a=2" assign a new value to "a", it simply makes "a
refer to a different object as Frederiq has explained recently on the
list. So the proper way to bind new values to an instance is to
generate a new instance like "a = MutableInt(3)", but then "a.set(3)"
might be acceptable in many cases. The fun of using a class is that
given it has the needed special methods defined you can easily use
this mutable-int-instance in expressions like in "a * 3".

--
groetjes, carel

Remco Gerlich

unread,
Dec 12, 2000, 7:19:34 PM12/12/00
to
Erno Kuusela <erno...@erno.iki.fi> wrote in comp.lang.python:

> In article <slrn93cotl....@pino.selwerd.nl>,
> scar...@pino.selwerd.nl (Remco Gerlich) writes:
>
> | Integers, longs, complex numbers, strings, functions, tuples, types, floats
> | and None are immutable. Most of these are obvious; the number 3 is the
> | number 3, why would you change that?!
>
> it is easy to think that when you know how things work in python.
> but, you could just as easily say, "a list containing the numbers 1, 2 and
> 3 is a list of 1, 2 and 3, why would you change that?!"

Yes, I realized that and therefore said "most of these...".

And it felt obvious at the time, a tuple is something I know from math
just like an integer, and a list is a pragmatic changing thingy that you
want to be able to change. But there have been a few other posts in the
thread that have made it less obvious, and I now see that a mutable int
can be useful; something like a UserInteger class besides the normal ints.
And integer literals would always be the immutable type so that 2+2 is
always 4, of course.

I'm now thinking that a mutable list type shouldn't have a literal, but
always be built from the immutable literal (since literals are by themselves
immutable, so a literal for a mutable type is strange).
Isn't that what Perl does?! (just an idea, i'm not saying that this
is a good idea ;)).

But I still feel that the current Python situation is rather simple, and
that it only looks complicated when people try to fit concepts from other
languages to it or when people like me try to explain it too much :).

--
Remco Gerlich

Fred Pacquier

unread,
Dec 13, 2000, 3:35:30 AM12/13/00
to
ka...@Glue.umd.edu (Roy Katz) said :

>On Tue, 12 Dec 2000, Fredrik Lundh wrote:
>> Sigh. The problem is that you keep using terms that mean
>> something for you, whether or not they apply to the current
>> situation. [snip]
>> If you want to learn something new, you have to stop doing
>> that. [snip]
>> Here's how it's done in Python:
>> [wonderful explanation snipped]
>
>Thank you very much, I understand now more or less how this works.
>Furthermore I appreciate your thoughtful, measured, and flame-free tone.

Seconded. I'm sure it's been useful to many other people who have been
"doing" Python for as long as you have (including me) without an
understanding that deep, whether they will admit to it or not.
As Fredrik says, this info certainly exists elsewhere and could be pieced
together from existing material. But having it summed up clearly and in few
words in one place can be a revelation, so this definitely needs to go in
python-snippets or FAQTS or somewhere... Thanks /F !

--
YAFAP : http://www.multimania.com/fredp/

Fredrik Lundh

unread,
Dec 13, 2000, 3:57:04 AM12/13/00
to
Fred Pacquier wrote:> As Fredrik says, this info certainly exists elsewhere and could be pieced

> together from existing material. But having it summed up clearly and in few
> words in one place can be a revelation, so this definitely needs to go in
> python-snippets or FAQTS or somewhere...

note to snippet/faqts maintainers (and other interested parties):

I've fixed a couple of typos, and posted the article here:

http://effbot.org/guides/python-objects.htm

if you repost the material, please include a pointer to that page.

thanks /F


Michael Hudson

unread,
Dec 13, 2000, 5:37:16 AM12/13/00
to
"Fredrik Lundh" <fre...@effbot.org> writes:

> Fred Pacquier wrote:> As Fredrik says, this info certainly exists elsewhere and could be pieced
> > together from existing material. But having it summed up clearly and in few
> > words in one place can be a revelation, so this definitely needs to go in
> > python-snippets or FAQTS or somewhere...
>
> note to snippet/faqts maintainers (and other interested parties):
>
> I've fixed a couple of typos, and posted the article here:
>
> http://effbot.org/guides/python-objects.htm
>

Now I want "M-x gnus-summary-reply-with-effbot-link"!

Good work,
M.

--
You sound surprised. We're talking about a government department
here - they have procedures, not intelligence.
-- Ben Hutchings, cam.misc

Alex Martelli

unread,
Dec 13, 2000, 7:27:28 AM12/13/00
to
"Aahz Maruch" <aa...@panix.com> wrote in message
news:9165he$lon$1...@panix3.panix.com...

> In article <r0pwvd5...@black.cs.washington.edu>,
> Daniel Wood <dan...@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

Alex Martelli

unread,
Dec 13, 2000, 9:23:51 AM12/13/00
to
"Simon B." <sbru...@bigfoot.com> wrote in message
news:915l04$l3i$1...@nnrp1.deja.com...
> In article <Pine.GSO.4.21.001212...@y.glue.umd.edu>,

> Roy Katz <ka...@Glue.umd.edu> wrote:
>
> > I've been programming in Python for three years now
> > and I understand only that passing an int or float is call-by-value,
> > otherwise it is call-by-reference
>
> Isn't that Java? It *certainly* isn't Python - *everything* is by
> reference in python. Unless I'm *really* confused...

Python and Java have identical argument-passing semantics
(well, except that Java has static compile-time constraints
on the types of actual vs formal parameters, of course).

Python does have a few more "immutable-types" than Java;
besides numbers and strings, that are immutable in both
languages, Python's tuples are immutable sequences (I do
not believe Java has anything like that), and Python's
instances may easily be made practically-immutable by
raising suitable exceptions in __setattr__ (not a very
frequently used possibility, admittedly), e.g:

class AlmostImmutable:
def __init__(self, initiallyMutable=None, **attributes):
self.__dict__.update(attributes)
self._lock(not initiallyMutable)
def _lock(onoff):
self.__dict__['_AlmostImmutable__locked'] = onoff
def __setattr__(self, name, value):
if self.__locked: raise AttributeError, "instance is locked"
self.__dict__[name] = value

inheriting by this mixin class can easily make your own
class-instances 'almost-immutable' (they CAN actually
be changed, via .__dict__ manipulations or use of the
provided ._lock(0) method, but 'normal' attempts at
changing them when 'locked' will raise AttributeError).


But the fact that a given 'thing' is not mutable does not
really affect the fact that a reference to it, rather than
a copy of its value, is what gets passed (in Java as well
as in Python). Maybe showing this mixin class might help
light dawn in this regard -- clearly, the instances of
classes inheriting from this one have two states, locked
and not locked, they're (ersatz:-) immutable in the locked
state, yet when such instances are passed as arguments the
same, identical mechanism is clearly being used, whatever
their current state may be...

However, I suspect the key issue is that people believe
an argument is 'by reference' if and only if *assigning to*
(as opposed to: calling suitable methods on) that formal
argument will somehow affect something in the caller. Since
such effects of 'assignment' to formal arguments never occur
in either Python or Java, it may be somewhat hard to convince
people that by-reference IS happening anyway -- that the
real issue is that the semantics they have in mind for
*assignment*, rather than what they have in mind for *argument
passing*, is what is really changed!-)


Alex

Steve Williams

unread,
Dec 13, 2000, 10:54:06 AM12/13/00
to
Alex Martelli wrote:

> [snip]

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

[snip]

I understand the Romans required an architect to stand under his arch as
the falsework was being removed.

Clarence Gardner

unread,
Dec 13, 2000, 10:54:37 AM12/13/00
to
On Tue, 12 Dec 2000, Fredrik Lundh wrote:
>
>All Python objects has the following:
>
> -- some content
> -- an unique identity (a integer, returned by id(x))
> -- a type (returned by type(x))
>
>You cannot change the identity.
>
>You cannot change the type.
>
[snip]

Nice summary, Fredrik!

I have no idea if it would have been such an enjoyable read if I didn't
already understand Python :)

Ng Pheng Siong

unread,
Dec 13, 2000, 12:16:33 PM12/13/00
to
According to Fredrik Lundh <fre...@effbot.org>:
> Realize that there are more than one way to do it.
^^^
"There are more than one way..."

"There is more than one way..." aka TIMTOWTDI.

Hmmm...


--
Ng Pheng Siong <ng...@post1.com> * http://www.post1.com/home/ngps

Alex Martelli

unread,
Dec 13, 2000, 11:25:14 AM12/13/00
to
"Steve Williams" <sandj.w...@gte.net> wrote in message
news:3A379CB4...@gte.net...

Neat idea (whether true or not -- that hardly matters!-), and
gives good (albeit mythical) background for Vitruvius' order
of priority.

The modern equivalent, in most cases, would be to require the
appropriate *managers* connected with a sw-development project
'stand under the arch' (or whatever we can come up with as a
fitting metaphor!).

The Roman architect was typically the prime contractor for the
building projects he undertook, as well as designer and
works-supervisor; as the building-art was well understood, the
chief reason for a building's early downfall would be, not
technical incompetence, but _greed_ -- trying to shave costs
(and increase profits) through inferior materials, shoddy
workmanship, &tc.

We don't really understand software development's technical
underpinnings quite as well as the Romans understood building's,
but I think that is not the key reason for most software's
defects; rather, I think most of them come from items that
stem more from management issues than strictly technical ones.

Too many features (else, marketing perceives, the product won't
sell) are scheduled to be delivered too early (else it won't
sell, and/or development will cost too much) -- often with
other brilliant 'cost-saving' ideas thrown in for good measure
(too few people, people not senior enough, not enough investment
in training, tools, and sundry productivity-enhancing doodads);
my take on it is that the often-displayed 'shoddy workmanship'
comes as a secondary and tertiary effect of all of this
'cost-saving' and feature-loading...


Alex

Fredrik Lundh

unread,
Dec 13, 2000, 12:27:51 PM12/13/00
to
Ng Pheng Siong wrote:
> According to Fredrik Lundh <fre...@effbot.org>:
> > Realize that there are more than one way to do it.
> ^^^
> "There are more than one way..."

http://www.dogma-2000.com/

</F>


Steve Williams

unread,
Dec 13, 2000, 12:39:48 PM12/13/00
to
Alex Martelli wrote:

> "Steve Williams" <sandj.w...@gte.net> wrote in message
> news:3A379CB4...@gte.net...
> > Alex Martelli wrote:
> >

> > > [lots of snip]


> >
> We don't really understand software development's technical
> underpinnings quite as well as the Romans understood building's,
> but I think that is not the key reason for most software's
> defects; rather, I think most of them come from items that
> stem more from management issues than strictly technical ones.
>

Here's an alternate viewpoint:

http://upside.com/Open_Season/3a3661271.html

Darren New

unread,
Dec 13, 2000, 7:03:25 PM12/13/00
to
Erno Kuusela wrote:
> | Having
> | x = 2 + 2
> | print x
> | result in anything except "4" is probably a *really* bad idea.
> | AFAIK, only FORTH and really old Fortrans allow this.
>
> agreed - but this is not something (sane) a mutable integer object
> would break.

Well, X is a variable, and you can already change the value in X.
2 is an integer.

What are we missing? I mean, the only integer that isn't mutable in that
statement is "2".

If you mean a cell (cf Eiffel) that stores a value and can get it back as an
object...
If you mean basically a shared variable, then that seems easy.

Mark Jackson

unread,
Dec 13, 2000, 12:38:28 PM12/13/00
to
"Alex Martelli" <ale...@yahoo.com> writes:
> "Steve Williams" <sandj.w...@gte.net> wrote in message
> news:3A379CB4...@gte.net...
> > Alex Martelli wrote:
> >
> > > [snip]
> >
> > > 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.
> >
> > [snip]
> >
> > I understand the Romans required an architect to stand under his arch as
> > the falsework was being removed.
>
> Neat idea (whether true or not -- that hardly matters!-), and
> gives good (albeit mythical) background for Vitruvius' order
> of priority.
>
> The modern equivalent, in most cases, would be to require the
> appropriate *managers* connected with a sw-development project
> 'stand under the arch' (or whatever we can come up with as a
> fitting metaphor!).

I'm sure I remember reading, sometime in 1999, that the top managers of
the Chinese national airline had been told to be onboard an in-air
flight at the Y2K transition. I have no idea whether the tale was
true, however.

--
Mark Jackson - http://www.alumni.caltech.edu/~mjackson
I know nothing about this subject but I do have
prejudices, which I am more than happy to share with you.
- Leon Botstein


Mikael Olofsson

unread,
Dec 14, 2000, 2:51:59 AM12/14/00
to

On 13-Dec-00 Steve Williams wrote:
> I understand the Romans required an architect to stand under his arch as
> the falsework was being removed.

That sounds like the Chinese way of dealing with the Y2K problem. All
managing directors of Chinese airline companies were ordered to book a
seat on one of their own flights the night between New Year's Eve and
New Year's Day.

I-read-that-in-the-newspaper-so-it-must-be-true-ly y'rs

/Mikael

-----------------------------------------------------------------------
E-Mail: Mikael Olofsson <mik...@isy.liu.se>
WWW: http://www.dtr.isy.liu.se/dtr/staff/mikael
Phone: +46 - (0)13 - 28 1343
Telefax: +46 - (0)13 - 28 1339
Date: 14-Dec-00
Time: 08:42:55

/"\
\ / ASCII Ribbon Campaign
X Against HTML Mail
/ \

This message was sent by XF-Mail.
-----------------------------------------------------------------------

Alex Martelli

unread,
Dec 14, 2000, 3:56:11 AM12/14/00
to
"Darren New" <dn...@san.rr.com> wrote in message
news:3A380E4E...@san.rr.com...

> Erno Kuusela wrote:
> > | Having
> > | x = 2 + 2
> > | print x
> > | result in anything except "4" is probably a *really* bad idea.
> > | AFAIK, only FORTH and really old Fortrans allow this.
> >
> > agreed - but this is not something (sane) a mutable integer object
> > would break.
>
> Well, X is a variable, and you can already change the value in X.

This _may_ harbor a slight misconception, coming from other languages,
that (in more complex cases) may interfere with optimal understanding
of Python.

There is no value *IN* x.

A variable *REFERS TO* 'a value' (aka 'an object').

The distinction is not very important for immutable values (objects):
although they're not really 'IN' any of the variables (or other
'slots') that REFER TO them, you may still write perfectly good
Python code even if labouring under a misconception that they are.

But as soon as mutable values (objects) enter the picture, then
thinking of values (objects) as being IN variables (or other slots)
brings you nothing but trouble. It's a good mental model for,
say, C. It's a terrible one for Python (or, as it happens, Java)...

It's a minor point, but getting into the habit of saying 'changing
what value X refers to' (when you mean peeling the postIt-like
'tag' that we call X, which can be affixed to different objects
at different times), or equivalently 'rebinding X to another value',
can, I think, help avoid certain annoying 'mental slips'...


Alex

Rainer Deyke

unread,
Dec 14, 2000, 2:42:26 PM12/14/00
to
"Alex Martelli" <ale...@yahoo.com> wrote in message
news:91a1v...@news2.newsguy.com...

> There is no value *IN* x.
>
> A variable *REFERS TO* 'a value' (aka 'an object').

If somebody really wants mutable integer objects, they're not that hard to
create.

class MutableInt(UserInt.UserInt):
def set(self, value):
self.data = value

x = MutableInt(2) + MutableInt(2)
print x
x.set(5)
print x


--
Rainer Deyke (ro...@rainerdeyke.com)
Shareware computer games - http://rainerdeyke.com
"In ihren Reihen zu stehen heisst unter Feinden zu kaempfen" - Abigor


Alex Martelli

unread,
Dec 14, 2000, 3:47:02 PM12/14/00
to
"Rainer Deyke" <ro...@rainerdeyke.com> wrote in message
news:Co9_5.25465$x6.13...@news2.rdc2.tx.home.com...

> "Alex Martelli" <ale...@yahoo.com> wrote in message
> news:91a1v...@news2.newsguy.com...
> > There is no value *IN* x.
> >
> > A variable *REFERS TO* 'a value' (aka 'an object').
>
> If somebody really wants mutable integer objects, they're not that hard to
> create.
>
> class MutableInt(UserInt.UserInt):
> def set(self, value):
> self.data = value

UserInt is not in the Python 2 docs, though it's nice to hear it exists:-).

Anyway, I had already provided a more generic class Mutable elsewhere
on (this or a parallel) thread 1-2 days ago -- including the explanation
of why I want a 'return value' to end this set statement...:-)


Alex

Rainer Deyke

unread,
Dec 14, 2000, 7:51:35 PM12/14/00
to
"Alex Martelli" <ale...@yahoo.com> wrote in message
news:91bbq...@news1.newsguy.com...

> "Rainer Deyke" <ro...@rainerdeyke.com> wrote in message
> news:Co9_5.25465$x6.13...@news2.rdc2.tx.home.com...
> > "Alex Martelli" <ale...@yahoo.com> wrote in message
> > news:91a1v...@news2.newsguy.com...
> > > There is no value *IN* x.
> > >
> > > A variable *REFERS TO* 'a value' (aka 'an object').
> >
> > If somebody really wants mutable integer objects, they're not that hard
to
> > create.
> >
> > class MutableInt(UserInt.UserInt):
> > def set(self, value):
> > self.data = value
>
> UserInt is not in the Python 2 docs, though it's nice to hear it
exists:-).

Actually it doesn't, but it's trivial (if tedious) to implement.

Darren New

unread,
Dec 14, 2000, 11:13:36 PM12/14/00
to
Alex Martelli wrote:
> > Well, X is a variable, and you can already change the value in X.
>
> This _may_ harbor a slight misconception, coming from other languages,
> that (in more complex cases) may interfere with optimal understanding
> of Python.
>
> There is no value *IN* x.
>
> A variable *REFERS TO* 'a value' (aka 'an object').

Well, I was being sloppy, but I did my graduate degree with Smalltalk so I'm
used to the model. I appriciate the attempt to clarify, tho. :-) The value
*in* X is the reference to the object, which is why asking whether it's
pass-by-value or pass-by-reference is confusing; it's
pass-reference-by-value.

My point was, you don't *want* mutable integers. You want something else
that holds a pointer/reference/etc to an integer where you can change the
pointer. And X is such a thing already. The only problem is that you can't
share X, but that's a different problem, regardless of whether it's an
integer or a list. But if you want a single copy of a mutable integer, you
can implement it with a variable.

Alex Martelli

unread,
Dec 15, 2000, 8:13:20 AM12/15/00
to
"Rainer Deyke" <ro...@rainerdeyke.com> wrote in message
news:rWd_5.26820$x6.14...@news2.rdc2.tx.home.com...
[snip]

> > > class MutableInt(UserInt.UserInt):
> > > def set(self, value):
> > > self.data = value
> >
> > UserInt is not in the Python 2 docs, though it's nice to hear it
> exists:-).
>
> Actually it doesn't, but it's trivial (if tedious) to implement.

But, if UserInt is not a funky metaclass, how will MutableInt live
up to its name? Surely it should at least redefine all of the
in-place methods...:

x = y = MutableInt(23)
x += 1

I would expect y's value-as-integer to be 24 now. So MutableInt
should implement __iadd__ (which the Python 2 docs only mention
in passing in one place, while talking of sequence and mapping
types, but that one _is_ a doc booboo, right?).


Alex

Rainer Deyke

unread,
Dec 15, 2000, 11:38:47 AM12/15/00
to
"Alex Martelli" <ale...@yahoo.com> wrote in message
news:91d5e...@news1.newsguy.com...

> "Rainer Deyke" <ro...@rainerdeyke.com> wrote in message
> news:rWd_5.26820$x6.14...@news2.rdc2.tx.home.com...
> [snip]
> > > > class MutableInt(UserInt.UserInt):
> > > > def set(self, value):
> > > > self.data = value
> > >
> > > UserInt is not in the Python 2 docs, though it's nice to hear it
> > exists:-).
> >
> > Actually it doesn't, but it's trivial (if tedious) to implement.
>
> But, if UserInt is not a funky metaclass, how will MutableInt live
> up to its name? Surely it should at least redefine all of the
> in-place methods...:
>
> x = y = MutableInt(23)
> x += 1

Yes, in-place modification should be supported. I had something like this
in mind:

class UserInt:
def __init__(self, value):
self.data = value
def __add__(self, other):
if isinstance(other, UserInt):
return self.__class__(self.data + other.data)
else:
return self.__class__(self.data + other)
__radd__ = __add__
def __iadd__(self, other):
if isinstance(other, UserInt):
self.data += other.data
else:
self.data += other
# Repeat for all other operations

UserInt as written is more properly UserNumber, since it supports longs ints
and floats.

Rainer Deyke

unread,
Dec 15, 2000, 12:16:33 PM12/15/00
to
"Rainer Deyke" <ro...@rainerdeyke.com> wrote in message
news:rOr_5.31120$x6.15...@news2.rdc2.tx.home.com...

> Yes, in-place modification should be supported. I had something like this
> in mind:
>
> class UserInt:
> def __init__(self, value):
> self.data = value
> def __add__(self, other):
> if isinstance(other, UserInt):
> return self.__class__(self.data + other.data)
> else:
> return self.__class__(self.data + other)
> __radd__ = __add__
> def __iadd__(self, other):
> if isinstance(other, UserInt):
> self.data += other.data
> else:
> self.data += other
> # Repeat for all other operations
>
> UserInt as written is more properly UserNumber, since it supports longs
ints
> and floats.

Of course __iadd__ actually belongs in MutableInt instead of UserInt, but
that didn't occur to me until after I'd written it.

Quinn Dunkan

unread,
Dec 16, 2000, 9:01:08 PM12/16/00
to
On Fri, 15 Dec 2000 16:38:47 GMT, Rainer Deyke <ro...@rainerdeyke.com> wrote:
>Yes, in-place modification should be supported. I had something like this
>in mind:
>
>class UserInt:
> def __init__(self, value):
> self.data = value
> def __add__(self, other):
> if isinstance(other, UserInt):
> return self.__class__(self.data + other.data)
> else:
> return self.__class__(self.data + other)
> __radd__ = __add__
> def __iadd__(self, other):
> if isinstance(other, UserInt):
> self.data += other.data
> else:
> self.data += other
> # Repeat for all other operations
>
>UserInt as written is more properly UserNumber, since it supports longs ints
>and floats.

Just as a matter of style, would it be superior to add a __coerce__ method
that knows how to coerce ints, longs, and floats into UserInts, or make an
explicit check on each method? __coerce__ saves a lot of typing, but I'm
generally wary of implicit things like coercion. When I implemented a class
like this (a vector, actually), I used __coerce__, but after trying to wrap my
brain around the control flow, I was thinking maybe I wouldn't next time, even
though it seems to work fine.

Is this fear unfounded? Is there a better way?

Quinn Dunkan

unread,
Dec 16, 2000, 9:06:55 PM12/16/00
to
On Fri, 15 Dec 2000 16:38:47 GMT, Rainer Deyke <ro...@rainerdeyke.com> wrote:
>Yes, in-place modification should be supported. I had something like this
>in mind:
>
>class UserInt:
> def __init__(self, value):
> self.data = value
> def __add__(self, other):
> if isinstance(other, UserInt):
> return self.__class__(self.data + other.data)
> else:
> return self.__class__(self.data + other)
> __radd__ = __add__
> def __iadd__(self, other):
> if isinstance(other, UserInt):
> self.data += other.data
> else:
> self.data += other
> # Repeat for all other operations
>
>UserInt as written is more properly UserNumber, since it supports longs ints
>and floats.

Just as a matter of style, would it be superior to add a __coerce__ method

Quinn Dunkan

unread,
Dec 16, 2000, 9:09:26 PM12/16/00
to
On Fri, 15 Dec 2000 16:38:47 GMT, Rainer Deyke <ro...@rainerdeyke.com> wrote:
>Yes, in-place modification should be supported. I had something like this
>in mind:
>
>class UserInt:
> def __init__(self, value):
> self.data = value
> def __add__(self, other):
> if isinstance(other, UserInt):
> return self.__class__(self.data + other.data)
> else:
> return self.__class__(self.data + other)
> __radd__ = __add__
> def __iadd__(self, other):
> if isinstance(other, UserInt):
> self.data += other.data
> else:
> self.data += other
> # Repeat for all other operations
>
>UserInt as written is more properly UserNumber, since it supports longs ints
>and floats.

Just as a matter of style, would it be superior to add a __coerce__ method

Quinn Dunkan

unread,
Dec 16, 2000, 9:12:05 PM12/16/00
to
On Fri, 15 Dec 2000 16:38:47 GMT, Rainer Deyke <ro...@rainerdeyke.com> wrote:
>Yes, in-place modification should be supported. I had something like this
>in mind:
>
>class UserInt:
> def __init__(self, value):
> self.data = value
> def __add__(self, other):
> if isinstance(other, UserInt):
> return self.__class__(self.data + other.data)
> else:
> return self.__class__(self.data + other)
> __radd__ = __add__
> def __iadd__(self, other):
> if isinstance(other, UserInt):
> self.data += other.data
> else:
> self.data += other
> # Repeat for all other operations
>
>UserInt as written is more properly UserNumber, since it supports longs ints
>and floats.

Just as a matter of style, would it be superior to add a __coerce__ method

Quinn Dunkan

unread,
Dec 16, 2000, 9:14:21 PM12/16/00
to
On Fri, 15 Dec 2000 16:38:47 GMT, Rainer Deyke <ro...@rainerdeyke.com> wrote:
>Yes, in-place modification should be supported. I had something like this
>in mind:
>
>class UserInt:
> def __init__(self, value):
> self.data = value
> def __add__(self, other):
> if isinstance(other, UserInt):
> return self.__class__(self.data + other.data)
> else:
> return self.__class__(self.data + other)
> __radd__ = __add__
> def __iadd__(self, other):
> if isinstance(other, UserInt):
> self.data += other.data
> else:
> self.data += other
> # Repeat for all other operations
>
>UserInt as written is more properly UserNumber, since it supports longs ints
>and floats.

Just as a matter of style, would it be superior to add a __coerce__ method

Quinn Dunkan

unread,
Dec 16, 2000, 9:17:02 PM12/16/00
to
On Fri, 15 Dec 2000 16:38:47 GMT, Rainer Deyke <ro...@rainerdeyke.com> wrote:
>Yes, in-place modification should be supported. I had something like this
>in mind:
>
>class UserInt:
> def __init__(self, value):
> self.data = value
> def __add__(self, other):
> if isinstance(other, UserInt):
> return self.__class__(self.data + other.data)
> else:
> return self.__class__(self.data + other)
> __radd__ = __add__
> def __iadd__(self, other):
> if isinstance(other, UserInt):
> self.data += other.data
> else:
> self.data += other
> # Repeat for all other operations
>
>UserInt as written is more properly UserNumber, since it supports longs ints
>and floats.

Just as a matter of style, would it be superior to add a __coerce__ method

Rainer Deyke

unread,
Dec 16, 2000, 10:26:33 PM12/16/00
to
"Quinn Dunkan" <qu...@dinar.ugcs.caltech.edu> wrote in message
news:slrn93o7j4...@dinar.ugcs.caltech.edu...

__coerce__ would probably have been superior, since it eliminates duplicate
code and more closely resembles the way real integers work in Python.

Alex Martelli

unread,
Dec 17, 2000, 4:43:54 AM12/17/00
to
"Rainer Deyke" <ro...@rainerdeyke.com> wrote in message
news:JnW_5.37708$x6.18...@news2.rdc2.tx.home.com...
[snip]
> > >class UserInt:
[snip]
> > > def __iadd__(self, other):
[snip]

> > Just as a matter of style, would it be superior to add a __coerce__
method
> > that knows how to coerce ints, longs, and floats into UserInts, or make
an
[snip]

> __coerce__ would probably have been superior, since it eliminates
duplicate
> code and more closely resembles the way real integers work in Python.

__coerce__ is what I had used in my generic Mutable class, previously
posted, together with a __getattr__ and a few others, to try and mimic
a variety of objects it could be holding by delegating stuff to whatever
it's holding in a way reasonably economical of code.

But it doesn't really work for __iadd__ and friends, does it? Unless I'm
missing something, those have to be implemented one by one. Maybe
__getattr__ tricks could help -- if name.startswith('__i'), one could use
name.replace('__i','__',1) to look a function up in library module
'operator', etc. But that doesn't exactly feel very 'clean' to me. (The
performance issues could be ameliorated by having Mutable instances
cache a directory of such methods once looked-up and built, but that
doesn't make the overall architecture any cleaner, it seems to me).


Alex

Quinn Dunkan

unread,
Dec 17, 2000, 6:57:13 AM12/17/00
to
On 17 Dec 2000 02:01:08 GMT, Quinn Dunkan <qu...@dinar.ugcs.caltech.edu> wrote:
[ 6 times ]

Argh, sorry about the multiple posts.

Note to self: when newsreader says "Post failed, try again? (y/n) " what it
*really* means is "Post succeeded, make a fool of yourself on Usenet? (y/n) ".

Stefan Franke

unread,
Dec 18, 2000, 5:29:23 PM12/18/00
to
On 17 Dec 2000 11:57:13 GMT, qu...@euro.ugcs.caltech.edu (Quinn Dunkan) wrote:

>Note to self: when newsreader says "Post failed, try again? (y/n) " what it
>*really* means is "Post succeeded, make a fool of yourself on Usenet? (y/n) ".

<grin> You aren't using Agent, are you?

deja-vou-ly y'rs
Stefan

0 new messages