Python vs. Ruby

6 views
Skip to first unread message

Fred

unread,
Dec 31, 2002, 9:37:46 AM12/31/02
to
Hello all.

I know Python and have come to love it very much. Nearly all of my
scripting tasks with large databases are written in it.

My question is this -- what are the qualitative differences between
Python and Ruby? Does Ruby has any strengths, either in the language
itself or its available libraries, that are better than Python? Or are
they pretty much even?

Also, on the issue of threading -- does Ruby have better support for
threading than Python? Or are they pretty much equal?

Thanks in advance for all of your responses.

-Fred

Lyle Johnson

unread,
Dec 31, 2002, 10:16:21 AM12/31/02
to
Fred wrote:

> My question is this -- what are the qualitative differences between
> Python and Ruby? Does Ruby has any strengths, either in the language
> itself or its available libraries, that are better than Python? Or are
> they pretty much even?

This has been discussed to death in the past and so you should be able
to dig up a lot of information with your search engine of choice.
However, this entry (now a few years old) from the Ruby FAQ presents one
Python user's opinion of the Ruby language:

http://www.rubycentral.com/faq/rubyfaq-2.html

What it doesn't address is the issue of available libraries, and here
Python wins, hands-down. In most cases, Ruby equivalents for your
favorite Python libraries are in fact available -- but the trick can be
finding them, or finding English-language documentation for them (as
many are developed in Japan).

> Also, on the issue of threading -- does Ruby have better support for
> threading than Python? Or are they pretty much equal?

No, Ruby and Python use very different threading implementations. Python
uses "native" or "system" threads (depending on your choice of
terminology) while Ruby uses "user" or "lightweight" threads.

Martin v. Löwis

unread,
Dec 31, 2002, 9:58:09 AM12/31/02
to
Fred <fred...@lrc.puissante.com> writes:

> My question is this -- what are the qualitative differences between
> Python and Ruby? Does Ruby has any strengths, either in the language
> itself or its available libraries, that are better than Python? Or are
> they pretty much even?

People often consider Ruby to have strengths in the language over
Python; they often give the "complete object orientation" and
"iterators" as advantages.

For the object orientation, they usually give numbers as examples,
which have methods just like any other object. Python supporters then
argue that Python has the same properties: numbers have always been
objects in Python, and since 2.2, they also have methods. I believe
that this similarity is shallow, and that the Ruby advantage is
irrelevant: The similarity is shallow as Ruby's methods on integers
are used regularly, whereas Python's methods on integers are used
rarely. The Ruby advantage is irrelevant, however, since both
languages are equally expressive in that area, and it makes no
difference whether you write 'xrange(1,10)' or '1 to 9'.

For iterators, Python people point out that Python also has an
iterators protocol now; Ruby people then think Python has stolen it
from Ruby. The similarity of Python and Ruby is deeper: in both
languages, you now can iterator over arbitrary objects. However, Ruby
has still an advantage, by supporting code blocks as objects; in
Python, you can only use the for loop for iteration.

On the library side, I don't think Ruby has anything to offer that
Python does not provide out of the box.

> Also, on the issue of threading -- does Ruby have better support for
> threading than Python? Or are they pretty much equal?

Ruby's support is worse. If you invoke a long-running call (such as a
socket read), all other threads are blocked. Python releases the
global interpreter lock for such calls, allowing other threads to run.

Regards,
Martin

Cameron Laird

unread,
Dec 31, 2002, 10:17:10 AM12/31/02
to
In article <3E11B4C5...@users.sourceforge.net>,
Lyle Johnson <ly...@users.sourceforge.net> wrote:
.
.
.

>What it doesn't address is the issue of available libraries, and here
>Python wins, hands-down. In most cases, Ruby equivalents for your
>favorite Python libraries are in fact available -- but the trick can be
>finding them, or finding English-language documentation for them (as
>many are developed in Japan).
.
.
.
My own experience is that Python's library is farther
ahead than you describe. Such a judgment depends
heavily on the kind of programming (networking?
statistical algorithms? GUI? text processing? ...)
one does, of course.
--

Cameron Laird <Cam...@Lairds.com>
Business: http://www.Phaseit.net
Personal: http://phaseit.net/claird/home.html

Francis Burton

unread,
Dec 31, 2002, 10:51:55 AM12/31/02
to
Lyle Johnson wrote:
> No, Ruby and Python use very different threading implementations. Python
> uses "native" or "system" threads (depending on your choice of
> terminology) while Ruby uses "user" or "lightweight" threads.

What difference does this make in practice? Is there somewhere I
can read about "native" vs "user" threads?

Francis

"Martin v. Löwis"

unread,
Dec 31, 2002, 12:12:30 PM12/31/02
to Francis Burton
Francis Burton wrote:
> What difference does this make in practice? Is there somewhere I
> can read about "native" vs "user" threads?

I guess there are many places on the net to read about this; this
distinction is fundamental, and probably discussed in any decent
introduction to threads. Essentially, user-level threads are implemented
without aid by the operating system; context-switches are initiated by
the application itself, rather than through preemption by the operating
system.

As the result, you won't see context switches in certain states in a
user-thread library, whereas thread switches can occur at any point when
using native threads. Also, the operating system can decide to run two
threads simultaneously on two processors in a multiprocessor machine.
For Python, the global interpreter lock takes away part of the
flexibility of native threads.

Comparing the two approaches in practice is only meaningful if you have
specific applications for which to compare them. For Python vs. Ruby,
the most notable difference is that blocking system calls block all
threads in Ruby, and just the calling thread in Python.

Regards,
Martin

John Roth

unread,
Dec 31, 2002, 7:11:36 PM12/31/02
to

"Fred" <fred...@lrc.puissante.com> wrote in message
news:_YhQ9.391356$GR5.1...@rwcrnsc51.ops.asp.att.net...

[sarcasm]
Ruby, of course, has brackets for code blocks which seems
to be a nicety that Python missed.
[/sarcasm]

It also has a solution to one of the ugliest warts in Python:
the fact that the .append(), .sort() and .reverse() methods
don't return an updated value, so you can't chain them.

The rest of the differences other people have pointed out
(other than the size of the library) are, to me, relatively
minor.

John Roth
>
> -Fred
>


Mike C. Fletcher

unread,
Dec 31, 2002, 7:55:00 PM12/31/02
to
Why post sarcasm to the Python list? To convince a Python user (or
heck, any user who's used to polite society ;) ) of the superiority of
Ruby you might try something along the lines of:

"""Ruby was created a long time after Python and PERL. It tries to be a
better language based in part on observing these older languages and
does these things differently as a result:

* implementing "purer" object orientation (methods on numbers and
the like)
o explain that some find this to be a "foolish consistency",
while others find it useful
o discuss the philosophical approach of both languages
o present thoughtful and well-reasoned explanations for your
point-of-view.
* using delimiters instead of indentation-based block structure
o give pros and cons, note the debates, explain why this is a
compelling argument against Python when most Python users
consider it a great strength of the language.
o If you don't feel like doing this, just point to the long
(and wearisome, and pointless) debates elsewhere.
* breaking object-orientation to return new objects when sorting
sequences ;)
o explain the Python wart (I too consider it a wart, but it's
an object-orientation-consistency-generated wart)
o explain why Ruby has a better approach, and how it fits into
the Ruby philosophy of purer OO
o might also want to explain that it's not a hard thing to fix
at some point in Python (if the powers-that-be want to) by
adding "sorted" and "reversed" methods to the list object
(no clue why you want "append" to create a new list, sounds
silly to me ;) ).
* put the rest of your reasoning here...

"""

Appologies if the sarcasm was intended to demonstrate the futility and
silliness of "my language is better than yours" threads (the sarcasm is
discussing what many consider to be one of the greatest features of
Python, the lack of extraneous syntax, so that's certainly possible).
There weren't any other strong indicators of ;) -y-ness (save that the
"sort" and "reverse" are "the ugliest warts" of Python (strong praise
indeed)), so I took it at face value.

Peace all,
Mike

John Roth wrote:

>"Fred" <fred...@lrc.puissante.com> wrote in message
>news:_YhQ9.391356$GR5.1...@rwcrnsc51.ops.asp.att.net...
>
>

...

>[sarcasm]
>Ruby, of course, has brackets for code blocks which seems
>to be a nicety that Python missed.
>[/sarcasm]
>
>It also has a solution to one of the ugliest warts in Python:
>the fact that the .append(), .sort() and .reverse() methods
>don't return an updated value, so you can't chain them.
>
>The rest of the differences other people have pointed out
>(other than the size of the library) are, to me, relatively
>minor.
>
>John Roth
>
>

...

_______________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://members.rogers.com/mcfletch/


Brian Quinlan

unread,
Dec 31, 2002, 7:37:57 PM12/31/02
to
John Roth wrote:
> It also has a solution to one of the ugliest warts in Python:
> the fact that the .append(), .sort() and .reverse() methods
> don't return an updated value, so you can't chain them.

This is by design in Python. It would be trivial to change these methods
to return self if it were considered desirable.

Cheers,
Brian


Justin Shaw

unread,
Dec 31, 2002, 10:54:03 PM12/31/02
to
> * breaking object-orientation to return new objects when sorting
> sequences ;)
<snip>

> o might also want to explain that it's not a hard thing to fix
> at some point in Python (if the powers-that-be want to) by
> adding "sorted" and "reversed" methods to the list object
> (no clue why you want "append" to create a new list, sounds
> silly to me ;) ).

You don't have to return a "new" list. What is non-object oriented about
this?

>>> class List(list):
def sort(self):
list.sort(self)
return self
def append(self, item):
list.append(self, item)
return self


>>> l = List([3, 2, 1])
>>> l.append(5).sort()
[1, 2, 3, 5]

Mike C. Fletcher

unread,
Dec 31, 2002, 11:51:10 PM12/31/02
to
Justin Shaw wrote:

>> * breaking object-orientation to return new objects when sorting
>> sequences ;)
>>
>>
><snip>
>
>
>> o might also want to explain that it's not a hard thing to fix
>> at some point in Python (if the powers-that-be want to) by
>> adding "sorted" and "reversed" methods to the list object
>> (no clue why you want "append" to create a new list, sounds
>> silly to me ;) ).
>>
>>
>
>You don't have to return a "new" list. What is non-object oriented about
>this?
>

...
"motivation" ;) . Oh, and "encapsulation" ;) .

The idea of object orientation is (roughly):
state with bound methods which modify that state
encapsulation of operation such that individual methods/objects have
obvious and minimal functionality, without concern for particular
use-cases not in the contract/semantics of the particular method/object

As I mentioned, I personally would prefer to go for a less pure OO
approach, but the discussion is whether returning self is OO. Returning
a new list is nicely OO in character. OO is littered with "create a new
object just like this one save for this aspect" methods, so:

t = s.sorted()

makes sense (you get back a new, sorted version of s from this method of
s). The fact that it fits nicely into functional style programming is
gravy. The method does exactly what it sounds like it should do (create
a sorted version). When you do:

s = s.sort()

which should sort return, the original or a copy?

Why (from an OO perspective, I fully understand the desirability from a
functional perspective) would it return a pointer to something you
already have a pointer to when the function has nothing to do
semantically with "get reference to object"? Purity says you're sorting
the object, not sorting the object and then returning random pieces of
state (such as the object reference (why not return a pointer to the
bound reverse method instead, since I often call that after calling sort
;) ?)).

But, in the end, really, who cares ;) :) . This thread is _by far_ the
most thought I've spent on this "issue" in the last year and a half of
coding Python 8hrs/day. Adding sorted() and reversed() to the built-in
class would probably be doable if people cared. But who knows, maybe
Guido will get a visit from a functional-programming-mafia type, reverse
his decision, and allow returning "self".

It's a whole new year (well, in 9 minutes), after all,
Mike

John Roth

unread,
Jan 1, 2003, 8:16:20 AM1/1/03
to

"Mike C. Fletcher" <mcfl...@rogers.com> wrote in message
news:mailman.1041382562...@python.org...

> Why post sarcasm to the Python list?

To point out that any language that adds unnecessary syntac
complexity and then claims superiority is baring its hubris in
public.

> To convince a Python user (or
> heck, any user who's used to polite society ;) ) of the superiority of
> Ruby you might try something along the lines of:

I wasn't intending to try to convince anyone of the superiority
of Ruby. Quite the contrary. The extra brackets have convinced me
that Ruby is not worth my time.

> """Ruby was created a long time after Python and PERL. It tries to be
a
> better language based in part on observing these older languages and
> does these things differently as a result:

AFIK, Ruby did not use Python as a base. It used PERL. All of the
documentation says, quite explicitly, that the author's motivation was
to create a better language than PERL.

> * breaking object-orientation to return new objects when sorting
> sequences ;)

I suppose I could care less about breaking "object orientation,"
but I'm not certain how. My objection is that it breaks chained
application by returning None rather than the obvious result that
anyone would expect from the name. The results in actual code
are rather ugly.

The arguement that one language is "more object-oriented"
than another is, IMNSHO, specious, and making that kind
of claim tends to trigger my b8t detector.

> o might also want to explain that it's not a hard thing to
fix
> at some point in Python (if the powers-that-be want to) by
> adding "sorted" and "reversed" methods to the list object
> (no clue why you want "append" to create a new list,
sounds
> silly to me ;) ).

"sorted()" and "reversed()" are great names, especially when used
in combination with the existing "sort()" and "reverse()" names. Thanks
for the suggestion.

Whether append() returns a *new* object or not is irrelevant to
my arguement. The fact that it returns None is the wart.

John Roth

John Roth

unread,
Jan 1, 2003, 8:18:29 AM1/1/03
to

"Brian Quinlan" <br...@sweetapp.com> wrote in message
news:mailman.1041381303...@python.org...

Of course it would be, and I regard the design as a major
inconsistency in Guido's thinking. Being novice friendly is
one thing, but penalizing everyone else by crippling chained
application is quite something else.

John Roth

>
> Cheers,
> Brian
>
>


Hans Nowak

unread,
Jan 1, 2003, 11:22:57 AM1/1/03
to
Fred wrote:
> Hello all.
>
> I know Python and have come to love it very much. Nearly all of my
> scripting tasks with large databases are written in it.
>
> My question is this -- what are the qualitative differences between
> Python and Ruby? Does Ruby has any strengths, either in the language
> itself or its available libraries, that are better than Python? Or are
> they pretty much even?

They seem to be roughly even, although Python seems to be more mature. Choosing
one over the other often appears to be a matter of liking or disliking
significant whitespace, explicit 'self', and Perlish syntax.

--
Hans (base64.decodestring('d3VybXlAZWFydGhsaW5rLm5ldA=='))
# decode for email address ;-)
The Pythonic Quarter:: http://www.awaretek.com/nowak/
Kaa:: http://www.awaretek.com/nowak/kaa.html

Rob Renaud

unread,
Jan 1, 2003, 5:01:09 PM1/1/03
to
<lot snipped>
"John Roth" <john...@ameritech.net> wrote in message
> Whether append() returns a *new* object or not is irrelevant to
> my arguement. The fact that it returns None is the wart.
>
> John Roth

It's consistant, not a wart from my perspective. If an object is
modified, it is not returned.

For every part of the (admittedly small) python library I know, that
is the case. Returning None is a hint that the object is modified.

So then the question becomes, why don't append(), sort(), reverse()
return a new list and not modify the original? Are mutable objects
themselves a wart on the langauge?

Peter Hansen

unread,
Jan 1, 2003, 5:47:36 PM1/1/03
to

I believe the response might be that, in at least the case of sort(),
and probably reverse() as well, creation of a new list would require
twice the memory, at least temporarily, which can be very undesirable.

-Peter

Brian Quinlan

unread,
Jan 1, 2003, 5:26:39 PM1/1/03
to
John Roth wrote:
> > > It also has a solution to one of the ugliest warts in Python:
> > > the fact that the .append(), .sort() and .reverse() methods
> > > don't return an updated value, so you can't chain them.
> >
> Of course it would be, and I regard the design as a major
> inconsistency in Guido's thinking. Being novice friendly is
> one thing, but penalizing everyone else by crippling chained
> application is quite something else.

It's not just newbie friendly, it's also a semantic aid for experts. If
chaining were typical in Python, then you would have no immediate
indication if a method is returning a new value or (a possibly mutated
version of) itself e.g. from reading this code:

foo.sort()
foo.count('a')

I can intuit that the sort is being done inplace. From this code:

foo.sort().count('a')

I cannot.

Since not using chained methods removes this semantic aid and it only
saves you the cost of typing an identifier, I think that the Python
design is reasonable.

Cheers,
Brian


John Roth

unread,
Jan 1, 2003, 6:15:49 PM1/1/03
to

"Peter Hansen" <pe...@engcorp.com> wrote in message
news:3E137008...@engcorp.com...

> Rob Renaud wrote:
> >
> > <lot snipped>
> > "John Roth" <john...@ameritech.net> wrote in message
> > > Whether append() returns a *new* object or not is irrelevant to
> > > my arguement. The fact that it returns None is the wart.
> > >
> > > John Roth
> >
> > It's consistant, not a wart from my perspective. If an object is
> > modified, it is not returned.
> >
> > For every part of the (admittedly small) python library I know, that
> > is the case. Returning None is a hint that the object is modified.

I wasn't aware that it was a consistent policy. That doesn't mean it
isn't, just that I wasn't aware of it if it is.

> > So then the question becomes, why don't append(), sort(), reverse()
> > return a new list and not modify the original? Are mutable objects
> > themselves a wart on the langauge?
>
> I believe the response might be that, in at least the case of sort(),
> and probably reverse() as well, creation of a new list would require
> twice the memory, at least temporarily, which can be very undesirable.

That's what I've always heard. In the case of .sort() and .reverse() the
performance hit (other than for storage allocation) would be neglible,
but for
.append() it involves copying the entire list as well as allocating
storage.

John Roth
>
> -Peter


David Eppstein

unread,
Jan 1, 2003, 6:43:35 PM1/1/03
to
In article <3759308d.03010...@posting.google.com>,
rpgn...@aol.com (Rob Renaud) wrote:

> So then the question becomes, why don't append(), sort(), reverse()
> return a new list and not modify the original? Are mutable objects
> themselves a wart on the langauge?

There is a level of purity beyond which a language can become a pretty
toy instead of a useful tool.

--
David Eppstein UC Irvine Dept. of Information & Computer Science
epps...@ics.uci.edu http://www.ics.uci.edu/~eppstein/

Bengt Richter

unread,
Jan 2, 2003, 6:33:04 AM1/2/03
to

Surely large lists would not be copied for every append? Wouldn't the
space be expanded in chunks? Even 1% extra free space for a million-item
list would give you 10k appends without reallocation and copying.

Regards,
Bengt Richter

Bengt Richter

unread,
Jan 2, 2003, 6:36:26 AM1/2/03
to
On Wed, 01 Jan 2003 15:43:35 -0800, David Eppstein <epps...@ics.uci.edu> wrote:

>In article <3759308d.03010...@posting.google.com>,
> rpgn...@aol.com (Rob Renaud) wrote:
>
>> So then the question becomes, why don't append(), sort(), reverse()
>> return a new list and not modify the original? Are mutable objects
>> themselves a wart on the langauge?
>
>There is a level of purity beyond which a language can become a pretty
>toy instead of a useful tool.
>

To the pure, everything, properly described, is pure ;-)

Regards,
Bengt Richter

Anders J. Munch

unread,
Jan 2, 2003, 8:34:49 AM1/2/03
to
"Rob Renaud" <rpgn...@aol.com> wrote in message
news:3759308d.03010...@posting.google.com...

As others have answered, for performance reasons. All in all, the
design choices for list's sort method make perfect sense.

I do miss a true functional sort though. More often than not,
performance is not that critical, and a functional sort would allow
simpler, clearer code.

Fortunately it's easy to write one yourself:

def sort(sequence, cmpfunc=None):
"""sort a sequence, returning a new list; if given, cmpfunc(x,y) -> -1, 0,
1"""
sorted = list(sequence)
if cmpfunc is None:
sorted.sort()
else:
sorted.sort(cmpfunc)
return sorted


How about adding this to the library somewhere?

my-preference-would-be-as-a-builtin-ly y'rs, Anders


John Roth

unread,
Jan 2, 2003, 9:03:40 AM1/2/03
to

"Anders J. Munch" <ande...@dancontrol.dk> wrote in message
news:3e143ffa$0$71611$edfa...@dread11.news.tele.dk...

This version unfortunately doesn't allow chained application. - it's
purely
a functional version. It shouldn't be all that hard to subclass list to
add
.sorted() and .reversed() methods, though.

John Roth
>
> my-preference-would-be-as-a-builtin-ly y'rs, Anders
>
>


Anders J. Munch

unread,
Jan 2, 2003, 9:27:05 AM1/2/03
to
"John Roth" <john...@ameritech.net> wrote:
> > How about adding this to the library somewhere?
>
> This version unfortunately doesn't allow chained application. - it's purely
> a functional version.

It was intended to be a purely functional version. It doesn't chain,
but then it doesn't need to. Say we add a functional reverse also:

def reverse(sequence):
"""reverse a sequence, returning a new list"""
reversed = list(sequence)
reversed.reverse()
return reversed

print reverse(sort([1,4,2,3]))

What more do you need?

- Anders


Mel Wilson

unread,
Jan 1, 2003, 9:15:33 PM1/1/03
to
In article <3759308d.03010...@posting.google.com>,
rpgn...@aol.com (Rob Renaud) wrote:
>So then the question becomes, why don't append(), sort(), reverse()
>return a new list and not modify the original? Are mutable objects
>themselves a wart on the langauge?

A mutable object is a sharable object. With a mutable
list you can change one element, or more elements, without
lousing up everybody else's binding to the list.

Regards. Mel.

Nicodemus

unread,
Jan 2, 2003, 11:13:10 AM1/2/03
to

Brian Quinlan wrote:

>It's not just newbie friendly, it's also a semantic aid for experts. If
>chaining were typical in Python, then you would have no immediate
>indication if a method is returning a new value or (a possibly mutated
>version of) itself e.g. from reading this code:
>
>foo.sort()
>foo.count('a')
>
>I can intuit that the sort is being done inplace. From this code:
>
>foo.sort().count('a')
>
>I cannot.
>
>Since not using chained methods removes this semantic aid and it only
>saves you the cost of typing an identifier, I think that the Python
>design is reasonable.
>
>Cheers,
>Brian
>


I agree. Quoting from the docs, in the section "2.2.6.4 Mutable Sequence
Types":

"The sort() and reverse() methods modify the list in place for economy
of space when sorting or reversing a large list. To remind you that they
operate by side effect, they don't return the sorted or reversed list."

I myself don't care much about chaining method calls, since the gains
are relatively small compared to the confusion (as explained by Brian)
that such a change would cause. I don't think adding "reversed()" and a
"sorted()" methods to lists would be a good idea (like suggested in
other emails in this thread), since it would cause even more confusion.

Farewell,
Nicodemus.


yaipa h.

unread,
Jan 2, 2003, 1:08:14 PM1/2/03
to
Fred,

Core language wise, they're equal... follow your heart as
your purse will tell you Java/Perl.

On a personal note, I love Python for it's ease of use, but the
robust modules keep me coming back. I can count on Python to
have a Perl module counter part done in about six months and
for it to be of very high quality. If this were not true then
I would hold my nose and write Perl. If Ruby is six months behind
Python, then it is a year behind Perl (please excuse the gross
over simplification, but I make my point). Ask yourself, can I wait a
year or so for a new module to come out? Maybe, maybe not.

Regards,

yaipa.h


Fred <fred...@lrc.puissante.com> wrote in message news:<_YhQ9.391356$GR5.1...@rwcrnsc51.ops.asp.att.net>...

> Hello all.
>
> I know Python and have come to love it very much. Nearly all of my
> scripting tasks with large databases are written in it.
>
> My question is this -- what are the qualitative differences between
> Python and Ruby? Does Ruby has any strengths, either in the language
> itself or its available libraries, that are better than Python? Or are
> they pretty much even?
>

> Also, on the issue of threading -- does Ruby have better support for
> threading than Python? Or are they pretty much equal?
>
> Thanks in advance for all of your responses.
>

> -Fred

John Roth

unread,
Jan 3, 2003, 9:29:54 AM1/3/03
to

"Anders J. Munch" <ande...@dancontrol.dk> wrote in message
news:3e144c3a$0$71645$edfa...@dread11.news.tele.dk...

Something that chains properly.

John Roth

>
> - Anders
>
>


Anders J. Munch

unread,
Jan 3, 2003, 9:37:53 AM1/3/03
to
"John Roth" <john...@ameritech.net> wrote:
> "Anders J. Munch" <ande...@dancontrol.dk> wrote in message
> > print reverse(sort([1,4,2,3]))
> >
> > What more do you need?
>
> Something that chains properly.

What does that mean? What does chaining do for you that composition
doesn't?

- Anders


Andrew Bennetts

unread,
Jan 3, 2003, 9:48:28 AM1/3/03
to
On Fri, Jan 03, 2003 at 09:29:54AM -0500, John Roth wrote:
>
> "Anders J. Munch" <ande...@dancontrol.dk> wrote in message
> news:3e144c3a$0$71645$edfa...@dread11.news.tele.dk...
> >
> > def reverse(sequence):
> > """reverse a sequence, returning a new list"""
> > reversed = list(sequence)
> > reversed.reverse()
> > return reversed
> >
> > print reverse(sort([1,4,2,3]))
> >
> > What more do you need?
>
> Something that chains properly.

Really? How often would you want to call
l.sort().sort().reverse().reverse()? ;)

-Andrew.


Skip Montanaro

unread,
Jan 3, 2003, 10:05:39 AM1/3/03
to
>> > What more do you need?
>>
>> Something that chains properly.

Anders> What does that mean? What does chaining do for you that
Anders> composition doesn't?

Preserve references to the original object?

S


Anders J. Munch

unread,
Jan 3, 2003, 11:04:51 AM1/3/03
to
"Skip Montanaro" <sk...@pobox.com> wrote in message
news:mailman.1041608921...@python.org...

l[:] = reverse(sort(l))

- Anders


Mel Wilson

unread,
Jan 3, 2003, 2:04:49 PM1/3/03
to
In article <mailman.1041604867...@python.org>,

Andrew Bennetts <andrew-p...@puzzling.org> wrote:
>On Fri, Jan 03, 2003 at 09:29:54AM -0500, John Roth wrote:
>>
>> "Anders J. Munch" <ande...@dancontrol.dk> wrote in message
>> news:3e144c3a$0$71645$edfa...@dread11.news.tele.dk...
>> > What more do you need?
>>
>> Something that chains properly.
>
>Really? How often would you want to call
>l.sort().sort().reverse().reverse()? ;)

i = s.sort().index(a)

could return the rank of the value of `a` within the
values in `s`.

But I'm not personally comfortable with hiding that big
side effect inside an innocent-looking expression, even if
cognoscenti have learned to raise a red flag anytime they see
'.sort('. There's already enough entry-level confusion with

t = s
t.sort()

and finding the values in `s` have all moved.

Regards. Mel.


Still, we give up the right to write

i = s[:].sort().index(a)

Oh, well.

Anders J. Munch

unread,
Jan 4, 2003, 8:02:09 AM1/4/03
to
"Mel Wilson" <mwi...@the-wire.com> wrote:
>
> Still, we give up the right to write
>
> i = s[:].sort().index(a)

This is equivalent to (using my sort function):
i = sort(s).index(a)

functional-sort-comes-to-the-rescue-again-ly y'rs, Anders

Christopher A. Craig

unread,
Jan 6, 2003, 9:39:10 AM1/6/03
to
mwi...@the-wire.com (Mel Wilson) writes:

> But I'm not personally comfortable with hiding that big
> side effect inside an innocent-looking expression, even if
> cognoscenti have learned to raise a red flag anytime they see
> '.sort('. There's already enough entry-level confusion with

I'm rather suprised you're willing to hide the time loss in such an
innocent looking expression. If I have something that could take
several seconds to run, I'd really rather see it have its own line.

--
Christopher A. Craig <com-n...@ccraig.org>
I develop for Linux for a living, I used to develop for DOS. Going from
DOS to Linux is like trading a glider for an F117. - Lawrence Foard

Mel Wilson

unread,
Jan 6, 2003, 4:43:57 PM1/6/03
to
In article <mailman.104187321...@python.org>,

com-n...@ccraig.org (Christopher A. Craig) wrote:
>mwi...@the-wire.com (Mel Wilson) writes:
>
>> But I'm not personally comfortable with hiding that big
>> side effect inside an innocent-looking expression, even if
>> cognoscenti have learned to raise a red flag anytime they see
>> '.sort('. There's already enough entry-level confusion with
>
>I'm rather suprised you're willing to hide the time loss in such an
>innocent looking expression. If I have something that could take
>several seconds to run, I'd really rather see it have its own line.

That was the big side effect I referred to. I'm not
necessarily in love with putting expensive operations on
their own lines, but it's a shame go to all the trouble of
sorting a list and then throwing the result away, perhaps to
sort it all over again later. Better to bind it with a name
and re-use it.. which in Python, as you say, takes a
separate line of code. Of course, like others, if I needed
a sorted copy my first thought would be to write a function
(perhaps called sorted_copy) that built me one.

Regards. Mel.

Stuart D. Gathman

unread,
Jan 8, 2003, 3:33:07 PM1/8/03
to
On Thu, 02 Jan 2003 11:13:10 -0500, Nicodemus wrote:

> Brian Quinlan wrote:

> "The sort() and reverse() methods modify the list in place for economy
> of space when sorting or reversing a large list. To remind you that they
> operate by side effect, they don't return the sorted or reversed list."
>
> I myself don't care much about chaining method calls, since the gains
> are relatively small compared to the confusion (as explained by Brian)
> that such a change would cause. I don't think adding "reversed()" and a
> "sorted()" methods to lists would be a good idea (like suggested in
> other emails in this thread), since it would cause even more confusion.

Smalltalk has a special syntax for chaining methods get the best of both
worlds. The smalltalk operator ';' is already taken in Python, but let
me make a quick stab at a Python substitute:

aList.sort();.reverse() # aList.sort(); aList.reverse()

A statement cannot begin with '.', so ';.' means to invoke another method
on the same object.

--
Stuart D. Gathman <stu...@bmsi.com>
Business Management Systems Inc. Phone: 703 591-0911 Fax: 703 591-6154
"Confutatis maledictis, flamis acribus addictis" - background song for
a Microsoft sponsored "Where do you want to go from here?" commercial.

Andrew Dalke

unread,
Jan 8, 2003, 4:04:38 PM1/8/03
to Stuart D. Gathman
Stuart D. Gathman wrote:
> The smalltalk operator ';' is already taken in Python, but let
> me make a quick stab at a Python substitute:
>
> aList.sort();.reverse() # aList.sort(); aList.reverse()
>
> A statement cannot begin with '.', so ';.' means to invoke another method
> on the same object.

Skipping the discussion for the syntax,

[].sort();.1

is legal, so it is posible for a statement to begin with '.'.

Personally, I don't want this sort of chaining.

Andrew
da...@dalkescientific.com

Erik Max Francis

unread,
Jan 8, 2003, 9:02:19 PM1/8/03
to
"Stuart D. Gathman" wrote:

> aList.sort();.reverse() # aList.sort(); aList.reverse()
>
> A statement cannot begin with '.', so ';.' means to invoke another
> method
> on the same object.

But is this awkwardness really worth it? One of Python's truly great
assets is its transparently readable code. I'm opposed on general
principle to anything which defeats that.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, USA / 37 20 N 121 53 W / &tSftDotIotE
/ \ Strange is our situation here upon earth.
\__/ Albert Einstein
ZOE / http://www.alcyone.com/pyos/zoe/
A simple Python OpenGL rendering engine.

Mike Meyer

unread,
Jan 9, 2003, 10:57:38 AM1/9/03
to
Erik Max Francis <m...@alcyone.com> writes:

> "Stuart D. Gathman" wrote:
> > aList.sort();.reverse() # aList.sort(); aList.reverse()
> > A statement cannot begin with '.', so ';.' means to invoke another
> > method
> > on the same object.
> But is this awkwardness really worth it? One of Python's truly great
> assets is its transparently readable code. I'm opposed on general
> principle to anything which defeats that.

True. However, the idea of specifying multiple methods on the same
object is consistent with recent changes (op=, for instance), and
seems useful enough to be worth writing a PEP for - *if* a readable
syntax can be invented for it.

I don't like ;.. I'm not sure I like the idea of tweaking the
semantics of statement at all. Maybe something like:

aList.(sort(), reverse())

Almost like using a tuple as the method, and it does all the
invocations in the tuple. Except it isn't a real tuple, because the
methods aren't reall calls.

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

Jack Diederich

unread,
Jan 9, 2003, 1:29:07 PM1/9/03
to
On Thu, Jan 09, 2003 at 03:57:38PM +0000, Mike Meyer wrote:
> Erik Max Francis <m...@alcyone.com> writes:
>
> > "Stuart D. Gathman" wrote:
> > > aList.sort();.reverse() # aList.sort(); aList.reverse()
> > > A statement cannot begin with '.', so ';.' means to invoke another
> > > method
> > > on the same object.
> > But is this awkwardness really worth it? One of Python's truly great
> > assets is its transparently readable code. I'm opposed on general
> > principle to anything which defeats that.
>
> True. However, the idea of specifying multiple methods on the same
> object is consistent with recent changes (op=, for instance), and
> seems useful enough to be worth writing a PEP for - *if* a readable
> syntax can be invented for it.
>
> I don't like ;.. I'm not sure I like the idea of tweaking the
> semantics of statement at all. Maybe something like:
>
> aList.(sort(), reverse())
>

Some people seem to like lists, etc to return an lvalue and other
people think it dilutes the language. To borrow from another language
would something like

import lvalues from pragma

be acceptable?
The return values that are currently None would then be self for all
calls in that module.

-jackdied

Andrew Dalke

unread,
Jan 9, 2003, 5:17:05 PM1/9/03
to
Jack Diederich wrote:
> Some people seem to like lists, etc to return an lvalue and other
> people think it dilutes the language. To borrow from another language
> would something like
>
> import lvalues from pragma
>
> be acceptable?

No because then it would be a dialect of Python and would make
others' code harder to understand and use.

> The return values that are currently None would then be self for all
> calls in that module.

I think you mean to say "currently have no explicit return value"

class Spam:
def eggs(self, i):
x = some.other.module()
if i > 3:
return x
elif i == 3:
return None

If i > 3 and x is None, this has an explicit return value, which
happens to be None.
If i == 2, it has an explicit return value of None.
If i < 3, it has an implicit return value of None.

Oh, and so far None isn't a reserved word (will be in the future)
so I could have had 'None = 3'


Try to please all the people all the time and you end up pleasing
few. In Guido we trust ;)

Andrew
da...@dalkescientific.com

Bengt Richter

unread,
Jan 9, 2003, 6:04:50 PM1/9/03
to
On Thu, 09 Jan 2003 15:57:38 GMT, Mike Meyer <m...@mired.org> wrote:

>Erik Max Francis <m...@alcyone.com> writes:
>
>> "Stuart D. Gathman" wrote:
>> > aList.sort();.reverse() # aList.sort(); aList.reverse()
>> > A statement cannot begin with '.', so ';.' means to invoke another
>> > method
>> > on the same object.
>> But is this awkwardness really worth it? One of Python's truly great
>> assets is its transparently readable code. I'm opposed on general
>> principle to anything which defeats that.
>
>True. However, the idea of specifying multiple methods on the same
>object is consistent with recent changes (op=, for instance), and
>seems useful enough to be worth writing a PEP for - *if* a readable
>syntax can be invented for it.
>
>I don't like ;.. I'm not sure I like the idea of tweaking the
>semantics of statement at all. Maybe something like:
>
> aList.(sort(), reverse())
>
>Almost like using a tuple as the method, and it does all the
>invocations in the tuple. Except it isn't a real tuple, because the
>methods aren't reall calls.

I'd rather reserve the xxx.(something) syntax for an alternate spelling
of getattr(xxx, something), where something is an expression resulting in a string.
E.g.,
for name in dir(thing): # when you want more than vars(thing).items()
print name, thing.(name)

Or maybe .( xxx ). for xxx special effects at the tokenizer level ;-)

How about getting your parens without a dot, using __call__ and passing bound methods?

>>> class L(list):
... def __call__(self, *ops):
... for op in ops:
... op()
... return self
...
>>> a = L([3,1,2])
>>> a(a.sort, a.reverse)
[3, 2, 1]
>>> a
[3, 2, 1]
>>> a(a.reverse) + [4]
[1, 2, 3, 4]
>>> a
[1, 2, 3]
>>> a(a.reverse) + [4]
[3, 2, 1, 4]

Alternatively:

>>> class L2(list):
... def __call__(self, *ops):
... l = self[:]
... for op in ops:
... op(l)
... return l
...
>>> b = L2([3,1,2])
>>> b
[3, 1, 2]
>>> b(list.reverse)
[2, 1, 3]
>>> b
[3, 1, 2]
>>> b(list.sort, list.reverse)
[3, 2, 1]
>>> b
[3, 1, 2]

Looks nicer with some local bindings though:

>>> sort = list.sort; reverse=list.reverse
>>> b
[3, 1, 2]
>>> b(sort)
[1, 2, 3]
>>> b
[3, 1, 2]
>>> b(sort, reverse)
[3, 2, 1]
>>> b(reverse)
[2, 1, 3]

Regards,
Bengt Richter

Mike Meyer

unread,
Jan 10, 2003, 10:38:27 AM1/10/03
to
bo...@oz.net (Bengt Richter) writes:

> On Thu, 09 Jan 2003 15:57:38 GMT, Mike Meyer <m...@mired.org> wrote:
> >Erik Max Francis <m...@alcyone.com> writes:
> >
> >> "Stuart D. Gathman" wrote:
> >> > aList.sort();.reverse() # aList.sort(); aList.reverse()
> >> > A statement cannot begin with '.', so ';.' means to invoke another
> >> > method
> >> > on the same object.
> >> But is this awkwardness really worth it? One of Python's truly great
> >> assets is its transparently readable code. I'm opposed on general
> >> principle to anything which defeats that.
> >
> >True. However, the idea of specifying multiple methods on the same
> >object is consistent with recent changes (op=, for instance), and
> >seems useful enough to be worth writing a PEP for - *if* a readable
> >syntax can be invented for it.
> >
> >I don't like ;.. I'm not sure I like the idea of tweaking the
> >semantics of statement at all. Maybe something like:
> >
> > aList.(sort(), reverse())
> >
> >Almost like using a tuple as the method, and it does all the
> >invocations in the tuple. Except it isn't a real tuple, because the
> >methods aren't reall calls.
>
> I'd rather reserve the xxx.(something) syntax for an alternate spelling
> of getattr(xxx, something), where something is an expression resulting in a string.

I think the multiple call shorthand is better than the getattr
shorthand. If I only get one, I want multiple calls. Or is there
already a PEP for the getattr shorthand?

> How about getting your parens without a dot, using __call__ and passing bound methods?

The whole point is to avoid having to list the bound object multiple
times, so no, that doesn't buy you anything.

Andrew Dalke

unread,
Jan 10, 2003, 12:36:58 PM1/10/03
to
Jack Diederich:

> Some people seem to like lists, etc to return an lvalue and other
> people think it dilutes the language. To borrow from another language
> would something like
>
> import lvalues from pragma
>
> be acceptable?
> The return values that are currently None would then be self for all
> calls in that module.

I futzed around with an idea for how to do this without an explicit
pragma. It implements your idea that "if it returns None, return the
original object instead" and without the qualifications I added about
the difference between explicit and implicit None return values.

As in another thread, "FOR ENTERTAINMENT PURPOSES ONLY"

class PragmaMethod:
def __init__(self, obj, method):
self.__dict__["_PragmaMethod__obj"] = obj
self.__dict__["_PragmaMethod__method"] = method
def __getatrr__(self, name):
return getattr(self.__method, name)
def __call__(self, *args, **kwargs):
x = self.__method(*args, **kwargs)
if x is None:
return Pragma(self.__obj)
return x

class Pragma:
def __init__(self, obj):
self.__dict__["_Pragma__obj"] = obj
def __getattr__(self, name):
x = getattr(self.__obj, name)
if callable(x):
return PragmaMethod(self.__obj, x)
return x

def test():
a = [1, 5, 3]
a = Pragma(a)
a.sort().reverse()
assert a == [5, 3, 1]
assert a[0] == 5
assert a.reverse()[0] == 1

if __name__ == "__main__":
test()

This could be expanded in many ways. For example, you
could make it so you list which attributes should be
handled this way as compared to normal behaviour. Perhaps
as

Pragma(a, ["sort", "reverse"])


Andrew Dalke
da...@dalkescientific.com

Bengt Richter

unread,
Jan 10, 2003, 1:01:46 PM1/10/03
to

Not that I know of. It just seemed natural ;-)

But your idea is growing on me. If you take the sequence to be args of a kind
of repeating text macro, where obj.(xxx,yyy,zzz) => obj.xxx; obj.yyy; obj.zzz
you would have a kind of "with" e.g.,

obj.(
a=123,
foo(),
x
)
=>
obj.a=123
obj.foo()
obj.x

Don't take too seriously ;-)

>
>> How about getting your parens without a dot, using __call__ and passing bound methods?
>
>The whole point is to avoid having to list the bound object multiple
>times, so no, that doesn't buy you anything.
>

You didn't comment on the alternative of passing _unbound_ methods
(or concise aliases, which I thought looked pretty clean) ;-)

I.e.,

aList(sort, reverse)

"and you can do it now"(TM) ;-)

Regards,
Bengt Richter

Michael Hudson

unread,
Jan 14, 2003, 8:08:45 AM1/14/03
to
"John Roth" <john...@ameritech.net> writes:

> That's what I've always heard. In the case of .sort() and .reverse()
> the performance hit (other than for storage allocation) would be
> neglible, but for .append() it involves copying the entire list as
> well as allocating storage.

The Python implementation isn't *that* dumb!

Cheers,
M.

--
Important data should not be entrusted to Pinstripe, as it may
eat it and make loud belching noises.
-- from the announcement of the beta of "Pinstripe" aka. Redhat 7.0

Michael Hudson

unread,
Jan 14, 2003, 8:12:16 AM1/14/03
to
Jack Diederich <ja...@performancedrivers.com> writes:

> To borrow from another language would something like
>
> import lvalues from pragma
>
> be acceptable?

Ooh, an easy one: No!

> The return values that are currently None would then be self for all
> calls in that module.

How about .sort() returning `self' 50% of the time, decided randomly?
:-)

Cheers,
M.

--
Any form of evilness that can be detected without *too* much effort
is worth it... I have no idea what kind of evil we're looking for
here or how to detect is, so I can't answer yes or no.
-- Guido Van Rossum, python-dev

Beni Cherniavsky

unread,
Jan 16, 2003, 7:46:06 AM1/16/03
to
On 2003-01-10, Bengt Richter wrote:

> But your idea is growing on me. If you take the sequence to be args of a kind

> of repeating text macro, whereobj.(xxx,yyy,zzz) => obj.xxx; obj.yyy; obj.zzz


> you would have a kind of "with" e.g.,
>
> obj.(
> a=123,
> foo(),
> x
> )
> =>
> obj.a=123
> obj.foo()
> obj.x
>
> Don't take too seriously ;-)
>

The DUEL extension to gdb (google for it) had lot's of cool typing-saving
features and one of my favourite things was the treatement of the dot
operator: it executed the right part with the fields of the left part
brought into scope (i.e. exactly what you propose, except that in Python
it suffers from scoping problems). DUEL is recommended reading, got me
interested in Icon (which I couldn't understand so I started designing my
own language based on these ideas :-)...

--
Beni Cherniavsky <cb...@tx.technion.ac.il>

There is an Excel spreadsheet here. Do you want to open it? y
There was a grid bug in the spreadsheet. The grid bug bites.

David Garamond

unread,
Jan 17, 2003, 11:05:17 PM1/17/03
to
John Roth wrote:
> It also has a solution to one of the ugliest warts in Python:
> the fact that the .append(), .sort() and .reverse() methods
> don't return an updated value, so you can't chain them.
>
> The rest of the differences other people have pointed out
> (other than the size of the library) are, to me, relatively
> minor.

that "ugliest wart" you mentioned is, to me, relatively minor (no, make
that one _really_ minor issue). in fact, many differences in language
syntaxes and features have become relatively minor to me.

we all have ideal expectations of what a language should be, and every
language we encounter will invariably fall short of that ideal. it's
impossible enough to design a perfect language, much less a perfect
language for everybody. every language has its warts and
that-one-feature that we think is just missing. python numbers can't
take methods, ruby doesn't have keyword arguments, python enforces
indentation, ruby can't produce compiled bytecodes, ... big deal. in the
end, it all boils down to "which language makes me more productive".

and to me, it seems that that language is ruby for now. i do love python
very much, but i was a perl programmer for years and coding in python
makes me miss things like builtin regex, statement modifiers, assignment
as expressions, and the many other conveniences that perl provides. ruby
tries _very hard_ to offer me those conveniences and so i'm pulled in.
because i was productive in perl, i can become productive quickly too in
ruby. python makes me productive too, but i guess not as much as ruby.
everybody's mileage may (and should) vary.

so nowadays i spent the majority of my coding hours in ruby. perl and
python comes second and third.

--
dave


Reply all
Reply to author
Forward
0 new messages