python 3's adoption

34 views
Skip to first unread message

Xah Lee

unread,
Jan 26, 2010, 6:47:35 PM1/26/10
to
Some thoughts about Python 3 Adoption.

Xah Lee, 2010-01-26

Some notes of Wikipedia readings related to Python.

Unladen Swallow, a new project from Google. It is a new python
compiler with the goal of 5 times faster than the de facto standand
implementation CPython. Also note Stackless Python, which is already
been used in some major commercial projects.

Was looking into what's new in Python 3. See: http://docs.python.org/dev/3.0/whatsnew/3.0.html.
From a quick reading, i don't really like it. Here's some highlights:

* Print is now a function. Great, much improvement.
* Many functions that return lists now returns “Views” or
“Iterators” Instead. A fucking fuck all fucked up shit. A extraneous
“oop engineering” complication. (See: Lambda in Python 3000)
* The cmp() function used in sort is basically gone, users are now
supposed to use the “key” parameter instead. This is a flying-face-
fuck to computer science. This would be the most serious fuckup in
python 3. (See: Sorting in Python and Perl)
* Integers by default is long. Great!
* Much more integrated unicode support, rewrite of most its text
or string semantics. Fantastic. Finally.

Am looking because i wonder if i should switch to python 3 for my own
few scripts, and rewrite my Python Tutorial for version 3. Am also
interested to know how python 3 is received by the computing industry.
Apparantly, a little search on the web indicates that vast majority of
python base have not switched, as expected, for many good reasons.
Vast majority of major python modules and tools have not switched.
Most linux distro have not switched, i don't find any large
corporation having adopted Python 3 (Google, Yahoo, Facebook,
NASA,... ). (sources: Source, Source) Basically, such a incompatible
change with trivial, ideological improvements, is too costy to switch.

I wonder, if by 2015, will most large corporate users have switched to
python 3. I give it a maybe. In today's Proliferation of Computing
Languages, such a major antic by Guido can just hurt itself. What is
he thinking? He of course thought himself as a god of lang designer,
who sincerely wants to push towards perfection, all future-looking.
Unfortunately, the tens of other major language designers all think
similarly.

perm archive of this post with possible updates here:
http://xahlee.org/comp/python3.html

Any comment on this?

Xah
http://xahlee.org/


Alan Harris-Reid

unread,
Jan 26, 2010, 7:55:41 PM1/26/10
to Xah Lee, pytho...@python.org
> ? http://xahlee.org/
Hello Xah,

I have no figures to base this on (just what I have read on the web),
but although the vast majority of comanies with big Python investments
are probably waiting for the 'critical mass' to use Python3 regularly
(oil-tanker effect), I would like to think that smaller operations are
experimenting with it more-and-more.

I think that for beginners who have dived into Python in the last 6-12
months (like me), it doesn't make sense to start with an older version.
I do not want to learn 'old' syntax and functions of a language, only to
have to learn the new versions when most developers upgrade to 3 - I
might as well learn the new syntax now and be ahead-of-the-game ;-) . I
know my choice of related packages (web-framework, ORM,
templating-engine) is very limited at present, but there are enough
branches and beta-versions around to help me with my learning-curve, and
I figure there will be some full-production-releases around by the time
I am 'fluent' with Python (12-18 months?).

Currently I am using Python 3.1 and CherryPy (3.20 rc1) every day, and
have had no serious problems (yet).

I would be interested to hear how other people are using Python 3, and
with what compatible packages.

Regards,
Alan Harris-Reid

Alf P. Steinbach

unread,
Jan 26, 2010, 8:28:00 PM1/26/10
to
I'm responding to the original message by Xah Lee, which is not carried by my
Usenet provider.

* Alan Harris-Reid:


> Xah Lee wrote:
>> Some thoughts about Python 3 Adoption.
>>
>> Xah Lee, 2010-01-26
>>
>> Some notes of Wikipedia readings related to Python.
>>
>> Unladen Swallow, a new project from Google. It is a new python
>> compiler with the goal of 5 times faster than the de facto standand
>> implementation CPython. Also note Stackless Python, which is already
>> been used in some major commercial projects.
>>
>> Was looking into what's new in Python 3. See:
>> http://docs.python.org/dev/3.0/whatsnew/3.0.html.
>> >From a quick reading, i don't really like it. Here's some highlights:
>>
>> * Print is now a function. Great, much improvement.

Actually not, IMHO. All it does is is to provide incompatibility. They forgot
Ronald Reagan's old maxim: if it don't need fixin', don't fix it.


>> * Many functions that return lists now returns �Views� or
>> �Iterators� Instead. A fucking fuck all fucked up shit. A extraneous
>> �oop engineering� complication. (See: Lambda in Python 3000)

On the contrary, this is a great improvement. It makes no sense to have to write
more code and less readable code for the common efficient case. And the default,
the way that takes 0.5 seconds less to do, does have a great influence on what
people choose, even in elections (Obama's latest "opt out" proposal is an
example that this principle is recognized even by the President of the United
States). When you want an explicit collection such as a 'list', introducing some
overhead for presumably a good reason, it's as easy as e.g. 'list(range(42))'.


>> * The cmp() function used in sort is basically gone, users are now

>> supposed to use the �key� parameter instead. This is a flying-face-


>> fuck to computer science. This would be the most serious fuckup in
>> python 3. (See: Sorting in Python and Perl)

I agree. :-)

Probably there must have been some rationale, but to put it bluntly removing the
comparator is more like moronic than pythonic. If the rationale was efficiency,
then a rational solution could be to provide two sort methods, like 'sort' using
direct comparisions and 'custom_sort' using a specified comparator. Come to
think of it, that door is still open, except for the language spec freeze.

It's possible to work around the removal of 'cmp' in various kludgy ways, but
you shouldn't have to "work around" a library sort routine.


>> * Integers by default is long. Great!

Yes, totally agree.

Nothing confuses the newbie or the now-and-then programmer so much as limited
range integers.

Well, perhaps floating point, but...


>> * Much more integrated unicode support, rewrite of most its text
>> or string semantics. Fantastic. Finally.

I'm not sure if the Unicode support is fantastic. I have the impression that
there are still some edges to iron out and corners to smooth, + bugs to kill.
But it's Very Good.


[snip]

Cheers,

- Alf

Grant Edwards

unread,
Jan 26, 2010, 8:38:37 PM1/26/10
to
On 2010-01-27, Alf P. Steinbach <al...@start.no> wrote:

> I'm responding to the original message by Xah Lee, which is
> not carried by my Usenet provider.

A Usenet provider that doesn't carry messages from Xah Lee.

So... many... jokes.....

--
Grant


alex23

unread,
Jan 26, 2010, 8:54:15 PM1/26/10
to
"Alf P. Steinbach" <al...@start.no> wrote:
> Actually not, IMHO. All it does is is to provide incompatibility. They forgot
> Ronald Reagan's old maxim: if it don't need fixin', don't fix it.
[...]

> Probably there must have been some rationale, but to put it bluntly removing the
> comparator is more like moronic than pythonic.

So in both cases, you haven't put any effort into researching why
these decisions were made, but you're happy to jump to conclusions
about the intelligence of the implementer(s) while regularly trotting
out complaints of ad hominem attacks against yourself.

The saddest part of all is you seem to consider yourself some kind of
educator.

Alf P. Steinbach

unread,
Jan 26, 2010, 9:08:29 PM1/26/10
to
* alex23:

Hi "alex23".

Ad hominem attacks like you try above, just reflect on the one doing it.

Adding in some obviously false assertions just makes you look even worse.

And posting anonymously, well, that article's got it all.

Such attacks constitute noise and, except for how they reflect on you, only noise.


Cheers & hth.,

- Alf

Steve Holden

unread,
Jan 26, 2010, 9:09:53 PM1/26/10
to pytho...@python.org
[Off-list]

<snort/> ;-)

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
PyCon is coming! Atlanta, Feb 2010 http://us.pycon.org/
Holden Web LLC http://www.holdenweb.com/
UPCOMING EVENTS: http://holdenweb.eventbrite.com/

Alf P. Steinbach

unread,
Jan 26, 2010, 9:12:37 PM1/26/10
to
* Steve Holden:

> [Off-list]
> alex23 wrote:
>> "Alf P. Steinbach" <al...@start.no> wrote:
>>> Actually not, IMHO. All it does is is to provide incompatibility. They forgot
>>> Ronald Reagan's old maxim: if it don't need fixin', don't fix it.
>> [...]
>>> Probably there must have been some rationale, but to put it bluntly removing the
>>> comparator is more like moronic than pythonic.
>> So in both cases, you haven't put any effort into researching why
>> these decisions were made, but you're happy to jump to conclusions
>> about the intelligence of the implementer(s) while regularly trotting
>> out complaints of ad hominem attacks against yourself.
>>
>> The saddest part of all is you seem to consider yourself some kind of
>> educator.
>
> <snort/> ;-)

Please don't post more noise and ad hominem attacks to the group, Steve.


- Alf

John Bokma

unread,
Jan 26, 2010, 10:04:53 PM1/26/10
to
"Alf P. Steinbach" <al...@start.no> writes:

> Please don't post more noise and ad hominem attacks to the group,
> Steve.

Funny that you talk about noise while replying yourself to noise. Xah
Lee is just a pathetic spammer. He's not going to reply in this
thread. He just shits out his stuff in as many groups as possible to
promote his website.

--
John Bokma j3b

Hacking & Hiking in Mexico - http://johnbokma.com/
http://castleamber.com/ - Perl & Python Development

Alf P. Steinbach

unread,
Jan 26, 2010, 10:12:07 PM1/26/10
to
* John Bokma:

> "Alf P. Steinbach" <al...@start.no> writes:
>
>> Please don't post more noise and ad hominem attacks to the group,
>> Steve.
>
> Funny that you talk about noise while replying yourself to noise. Xah
> Lee is just a pathetic spammer. He's not going to reply in this
> thread. He just shits out his stuff in as many groups as possible to
> promote his website.

Sorry, I didn't know.

Thanks for the heads-up.


Cheers,

- Alf

John Bokma

unread,
Jan 26, 2010, 10:18:04 PM1/26/10
to

My apologies for the harsh tone of my reply. I am more than tired of how
Xah Lee spams weekly, and shouldn't have assumed you were aware of that.

Terry Reedy

unread,
Jan 26, 2010, 10:37:45 PM1/26/10
to pytho...@python.org
On 1/26/2010 6:47 PM, Xah Lee wrote:
> Some thoughts about Python 3 Adoption.
>
> Xah Lee, 2010-01-26
>
> Some notes of Wikipedia readings related to Python.
>
> Unladen Swallow, a new project from Google. It is a new python
> compiler with the goal of 5 times faster than the de facto standand
> implementation CPython. Also note Stackless Python, which is already
> been used in some major commercial projects.
>
> Was looking into what's new in Python 3. See: http://docs.python.org/dev/3.0/whatsnew/3.0.html.
> From a quick reading, i don't really like it. Here's some highlights:
>
> * Print is now a function. Great, much improvement.

Something we agree on. For simple scripts, it is a bit of a nuisance,
but it eliminates kludgy special-case syntax for options, which are now
normal keyword arguments.

> * Many functions that return lists now returns “Views” or
> “Iterators” Instead. A fucking fuck all fucked up shit. A extraneous
> “oop engineering” complication. (See: Lambda in Python 3000)

Something we disagree on. I consider the shift from list or iterator
orientation a major advance. If you ever want to iterate a 10 million
item dict or map or filter a 100 million item sequence, you might then
see the point.

> * The cmp() function used in sort is basically gone, users are now
> supposed to use the “key” parameter instead. This is a flying-face-
> fuck to computer science. This would be the most serious fuckup in
> python 3. (See: Sorting in Python and Perl)

It is completely gone. Cmp was kludgy. Sort paid no attention to the
tri-state return but only paid attention to the less-than branch. Which
means a) that it was redundant with the less than method and that the
effort to split == from > was completely wasted. It is difficult to find
use cases where cmp= is superior to key=

> * Integers by default is long. Great!
> * Much more integrated unicode support, rewrite of most its text
> or string semantics. Fantastic. Finally.

What is missing now on Windows is better support from the OS, at least
with XP. I have not tried 3.1 on Win7 yet (and never touched Vista).


>
> Am looking because i wonder if i should switch to python 3 for my own
> few scripts, and rewrite my Python Tutorial for version 3.

I am writing my book on algorithms using 3.1 because of the above and
other improvements (consistent / and elimination of old classes, for
instance).

> Am also
> interested to know how python 3 is received by the computing industry.
> Apparantly, a little search on the web indicates that vast majority of
> python base have not switched,

Some people have panicked prematurely.

Guido never expected that working old apps would all be switched. There
is probably code still being run with 1.5 from 15 years ago. And there
will be 2.7 code running at least that far in the future.

Even before 3.0 was out, he also never expected major uptake until 3.2,
which is a year away. 3.0 was, well, a .0 release with a couple of .0
problems. 3.1 is pretty solid and modules are appearing for it.

> as expected, for many good reasons.
> Vast majority of major python modules and tools have not switched.

A few have, more will in the next year or after 3.2 is released, some
never will. The most important one, in my opinion, is numpy, since some
module authors who *want* to do a 3.x version are waiting on that.

> Most linux distro have not switched,

Have any switched to 2.6 yet, as the default? Some do have 3.1 version
available.

> i don't find any large
> corporation having adopted Python 3 (Google, Yahoo, Facebook,
> NASA,... ). (sources: Source, Source) Basically, such a incompatible
> change with trivial, ideological improvements, is too costy to switch.

The major reduction of redundancy by the overdue removal of obsolete
features makes it a much nicer language to learn than, say, 2.6. It is
much closer to the simplicity of 1.4, which is what I started with.

Terry Jan Reedy


Steven D'Aprano

unread,
Jan 27, 2010, 1:12:50 AM1/27/10
to
On Wed, 27 Jan 2010 02:28:00 +0100, Alf P. Steinbach wrote:

>>> * Print is now a function. Great, much improvement.
>
> Actually not, IMHO. All it does is is to provide incompatibility. They
> forgot Ronald Reagan's old maxim: if it don't need fixin', don't fix it.

print as a function is more consistent and more convenient than print as
a statement. Or to put it another way, print as a statement is less
consistent and convenient, and therefore in need of fixing. By Ronald
Reagan's aphorism, it should be fixed, and now does.

Of course there's a bit of a learning curve for those used to the old
ways, but in two years from now, I expect no-one will remember what the
fuss was about. Python 2.6 users will start their script with "from
__future__ import print_function", Python 2.7 users may not even need to
do that, and we'll all pity those stuck with 2.5 or 2.4.

>>> * Many functions that return lists now returns “Views” or
>>> “Iterators” Instead. A fucking fuck all fucked up shit. A extraneous
>>> “oop engineering” complication. (See: Lambda in Python 3000)


>
> On the contrary, this is a great improvement.

Agreed.


>>> * The cmp() function used in sort is basically gone, users are now

>>> supposed to use the “key” parameter instead. This is a flying-face-


>>> fuck to computer science. This would be the most serious fuckup in
>>> python 3. (See: Sorting in Python and Perl)
>
> I agree. :-)

I did too, when I first heard cmp was to be dumped. But I changed my mind
and now agree with the decision to drop cmp. Custom sorts are nearly
always much better written with key rather than cmp: key adds an O(N)
overheard to the sorting, while cmp makes sorting O(N**2). In other
words, key is *much* faster, and generally easier to write as well.

There may be a handful of rare applications where there is no obvious way
to convert a cmp function to a key, but they are vanishingly rare. I
think, if you search the archives, Paul Rubin may have come up with one
example. There are a number of recipes for easily converting cmp sorts to
key sorts.

I think, in my perfect world, list.sort() and sorted() should continue
being key based, while the standard library contained (perhaps in the
functools module?) a sort function that contains all the bells and
whistles. You want cmp, it's there, and you can pay the extra cost if you
need it. You want to sort multiple lists by the contents of one? One
import away. But keep the general sort() function lean and super-fast.

--
Steven

Paul Rubin

unread,
Jan 27, 2010, 1:23:11 AM1/27/10
to
Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> writes:
> print as a function is more consistent and more convenient than print as
> a statement.

Convenience is subjective, but the 3.x 'print' behavior is definitely
inconsistent (i.e. different from 2.x). The change makes a lot of my
code silently produce wrong results, too. I often print tuples to show
what a program is doing:

print (timestamp, 'transmogrified', blob)

which in 2.x prints a parenthesized tuple that I can later read back in
with eval. That line of code still prints a message, but in a different
format, instead of throwing an error.

Steven D'Aprano

unread,
Jan 27, 2010, 2:26:42 AM1/27/10
to
On Tue, 26 Jan 2010 22:23:11 -0800, Paul Rubin wrote:

> Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> writes:
>> print as a function is more consistent and more convenient than print
>> as a statement.
>
> Convenience is subjective, but the 3.x 'print' behavior is definitely
> inconsistent (i.e. different from 2.x).


Sorry, I meant consistent with the rest of Python, which mostly uses
functions/methods and only rarely statements (e.g. del and import).


> The change makes a lot of my
> code silently produce wrong results, too. I often print tuples to show
> what a program is doing:
>
> print (timestamp, 'transmogrified', blob)
>
> which in 2.x prints a parenthesized tuple that I can later read back in
> with eval. That line of code still prints a message, but in a different
> format, instead of throwing an error.


I don't pretend that the transition between statement and function syntax
will be anything but inconvenient, but I believe the end result will be
worth it.


--
Steven

Paul Rubin

unread,
Jan 27, 2010, 2:37:00 AM1/27/10
to
Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> writes:
> Sorry, I meant consistent with the rest of Python, which mostly uses
> functions/methods and only rarely statements (e.g. del and import).

yield, assert, if/else, return, etc. If we're after that kind of
consistency, why not get rid of all those statements too? They have
already partly done it with yield, and they ended up introducing a new
separate if/else expression syntax as an alternative to the statement.

> I don't pretend that the transition between statement and function syntax
> will be anything but inconvenient, but I believe the end result will be
> worth it.

This just seems like a gratuitous change with very little benefit.
Changing a bunch of list functions to instead return iterators is
a much deeper change that will cause larger amounts of breakage, but
it has quite a lot of benefits, so there's a stronger case for it.

Steven D'Aprano

unread,
Jan 27, 2010, 3:20:57 AM1/27/10
to
On Tue, 26 Jan 2010 23:37:00 -0800, Paul Rubin wrote:

> Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> writes:
>> Sorry, I meant consistent with the rest of Python, which mostly uses
>> functions/methods and only rarely statements (e.g. del and import).
>
> yield, assert, if/else, return, etc. If we're after that kind of
> consistency, why not get rid of all those statements too? They have
> already partly done it with yield, and they ended up introducing a new
> separate if/else expression syntax as an alternative to the statement.

Without becoming a purely functional language, you won't get rid of all
statements. In my opinion, outside of such purely functional languages
and unconventional languages like Forth, statements play a valuable role
in that they are controlling syntax. For example:

for, while, if, try, break, yield, return

are all used for flow control, and should remain as statements. But print
is not -- it's a function disguised as a statement. print, after all, is
just sugar for stdout.write, which is fine as far as it goes, but when
you want to do something slightly different from what the sugar does, it
becomes terribly inconvenient.

A consequence of print being a statement is that my modules are often
filled with functions and methods called "print_". Suppose I want to
print the type of each argument as well as it's value. I would like to do
this:


def decorator(pr):
def inner(*args, **kwargs):
args = [(type(a), a) for a in args]
pr(*args, **kwargs)
return inner

print = decorator(print)


and then use print as normal, but of course I can't. So instead I do
something like this:


def print_(*args, **kwargs):
args = [(type(a), a) for a in args]
kw = {'file': sys.stdout, 'sep': ' ', 'end': '\n'}
kw.update(kwargs)
if len(kw) != 3:
raise TypeError('invalid keyword argument')
file = kw['file']
sep = kw['sep']
end = kw['end']
for arg in args:
print >>file, (str(arg) + sep), # Don't forget the comma.
print >>file, end, # Another comma.


And then, I have to remember to call print_ instead of print.

--
Steven

Paul Rubin

unread,
Jan 27, 2010, 3:36:52 AM1/27/10
to
Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> writes:
> Without becoming a purely functional language, you won't get rid of all
> statements.

Why not? GCC lets you use any statement in an expression:

#include <stdio.h>

main()
{
int i, x, p=0;
x = ({ for (i=1; i<=10; i++) p += i; p;});
printf ("x=%d\n", x);
}

and C is certainly not a purely functional language.

> for, while, if, try, break, yield, return
> are all used for flow control, and should remain as statements.

What about assert, import, and pass?

Daniel Fetchinson

unread,
Jan 27, 2010, 4:35:00 AM1/27/10
to Python
>>> * Print is now a function. Great, much improvement.
>
> Actually not, IMHO. All it does is is to provide incompatibility.


What incompatibility are you exactly talking about?

Python 2.6.2 (r262:71600, Aug 21 2009, 12:23:57)
[GCC 4.4.1 20090818 (Red Hat 4.4.1-6)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print( 'hello' )
hello
>>> print 'hello'
hello
>>>

Yes, this is with python 2.6.2 which is in the 2.x line of releases. So?

Cheers,
Daniel

--
Psss, psss, put it down! - http://www.cafepress.com/putitdown

Steve Holden

unread,
Jan 27, 2010, 5:19:35 AM1/27/10
to pytho...@python.org

Remember that Guido stated (I think in the original FAQ entry for why
assignments don't produce results, but I could be wrong) that he
explicitly wanted Python to be a statement-based language.

Xah Lee

unread,
Jan 27, 2010, 6:40:38 AM1/27/10
to
Someone is badmouthing me, and it has been doing so over the years. I
feel obliged to post a off topic relpy. See:

• DreamHost.com and A Incidence of Harassment
http://xahlee.org/Periodic_dosage_dir/t2/harassment.html

• Why Can't You Be Normal?
http://xahlee.org/Netiquette_dir/why_cant_you_be_normal.html

Xah

Xah Lee

unread,
Jan 27, 2010, 7:26:00 AM1/27/10
to
On Jan 26, 3:47 pm, Xah Lee <xah...@gmail.com> wrote:

> * Many functions that return lists now returns “Views” or
> “Iterators” Instead. A fucking fuck all fucked up shit. A extraneous
> “oop engineering” complication. (See: Lambda in Python 3000)

See also:

“Iterators: Signs of Weakness in Object-Oriented Languages” (1992) By
Henry G Baker. http://home.pipeline.com/~hbaker1/Iterator.html

Xah wrote:
> * The cmp() function used in sort is basically gone, users are now
> supposed to use the “key” parameter instead. This is a flying-face-
> fuck to computer science. This would be the most serious fuckup in
> python 3. (See: Sorting in Python and Perl)

Steven D'Aprano wrote:
> I did too, when I first heard cmp was to be dumped. But I changed my mind
> and now agree with the decision to drop cmp. Custom sorts are nearly
> always much better written with key rather than cmp: key adds an O(N)
> overheard to the sorting, while cmp makes sorting O(N**2). In other
> words, key is *much* faster, and generally easier to write as well.

The reason cmp is a order slower is due to Python lang's limitation
and compiler implementation limitation.

• Sorting in Python and Perl
http://xahlee.org/perl-python/sort_list.html

the python lang, by the very nature of being a dynamic lang, makes it
hard for compiler analize and optimize a sort function call with cmp
argument that is equivalent to a key.

So, for practical reasons, i think a “key” parameter is fine. But
chopping off “cmp” is damaging. When your data structure is complex,
its order is not embedded in some “key”. Taking out “cmp” makes it
impossible to sort your data structure.

in the essay, i also gave a few examples of data structures where you
need a general means to specify the ordering function in order to
sort. Without a cmp, you'll need to munge your data by some decorate-
sort-dedecorate technique.

From another perspective, often it is considered a good principle of
design that the lang be a bit flexible to let programers do what they
want, instead of force them into one way. Python, being a loosely
typed lang, with so-called “duck typing”, in contrast to Java or OCaml
in different ways, certainly is more on the lose extreme of the lang
spectrum with respect to code construction. So, i don't see how python
3 people made the decision to removed cmp. (am pretty sure, at least
part of the reason, is a ill attitude towards functional programing
and lambda, lead by Guido.)

> There may be a handful of rare applications where there is no obvious way
> to convert a cmp function to a key, but they are vanishingly rare. I
> think, if you search the archives, Paul Rubin may have come up with one
> example. There are a number of recipes for easily converting cmp sorts to
> key sorts.

You say that it is rare. You are probably right. Though, that may just
be caused by the language itself and consequently the type of people
who uses it. If Python's lambda is not limited, and the python
community doesn't look down on lambda, it is likely cmp will used
more. The more your data structure becomes complex, the more cmp will
be needed.

> I think, in my perfect world, list.sort() and sorted() should continue
> being key based, while the standard library contained (perhaps in the
> functools module?) a sort function that contains all the bells and
> whistles. You want cmp, it's there, and you can pay the extra cost if you
> need it. You want to sort multiple lists by the contents of one? One
> import away. But keep the general sort() function lean and super-fast.

btw, is something like cmp still available in some module for sort?

Xah
http://xahlee.org/


Alf P. Steinbach

unread,
Jan 27, 2010, 9:57:14 AM1/27/10
to
* Daniel Fetchinson:

>>>> * Print is now a function. Great, much improvement.
>> Actually not, IMHO. All it does is is to provide incompatibility.
>
>
> What incompatibility are you exactly talking about?
>
> Python 2.6.2 (r262:71600, Aug 21 2009, 12:23:57)
> [GCC 4.4.1 20090818 (Red Hat 4.4.1-6)] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> print( 'hello' )
> hello
>>>> print 'hello'
> hello
>
> Yes, this is with python 2.6.2 which is in the 2.x line of releases. So?

I gather that your example is about code that technically executes fine with
both versions and produces the same result, i.e. that there is a subset with the
same syntax and semantics.

But 'print' calls that technically execute fine with both versions may and will
in general produce different results.

I.e. not just the syntax but also the semantics have changed:


>>> import sys
>>> sys.version
'2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)]'
>>>
>>> print( "2+2 =", 2+2 )
('2+2 =', 4)
>>> _


>>> import sys
>>> sys.version
'3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit (Intel)]'
>>>
>>> print( "2+2 =", 2+2 )
2+2 = 4
>>> _

Daniel Fetchinson

unread,
Jan 27, 2010, 10:26:37 AM1/27/10
to Python

True. However, as someone else pointed out in a neighbouring thread you can do

Python 2.6.2 (r262:71600, Aug 21 2009, 12:23:57)
[GCC 4.4.1 20090818 (Red Hat 4.4.1-6)] on linux2
Type "help", "copyright", "credits" or "license" for more information.

>>> from __future__ import print_function


>>> print( "2+2 =", 2+2 )
2+2 = 4
>>>

which gives 100% compatibility as far as print is concerned between 2.6 and 3.x.

So again, what sort of an incompatibility are you talking about
concerning 'print' between 2.6 and 3.x?

Alf P. Steinbach

unread,
Jan 27, 2010, 10:47:04 AM1/27/10
to
* Daniel Fetchinson:

That makes the code behave with 3.x syntax and semantics regarding print. I.e.
it chooses one language. It doesn't make them compatible: if they were, then you
wouldn't have to choose.

For example, it doesn't fix up 2.x code that prints tuples: incompatible, it
will still execute but no longer do what it was supposed to do.

But lest you focus down on that rare case, consider 2.x code that contains

print "2+2", 2

All such statements need to be fixed up in a 2->3 transition. Adding __future__
just makes the code invalid, it doesn't give you any shred of compatibility for
this. A code rewrite can be partially automated like 2to3 but the
incompatibility needlessly introduces an additional set of things that Can Go
Wrong(TM), and with Murphy present, as He always is, well.


> So again, what sort of an incompatibility are you talking about
> concerning 'print' between 2.6 and 3.x?

Syntax and semantics. They're different.

Stefan Behnel

unread,
Jan 27, 2010, 11:24:37 AM1/27/10
to
Xah Lee, 27.01.2010 00:47:
> Any comment on this?

No, sorry. Not worth bothering.

Stefan

Daniel Fetchinson

unread,
Jan 27, 2010, 11:58:10 AM1/27/10
to Python

Of course it makes them compatible. I'm not saying any print-related
code in python 2.6 is valid python 3 code, but that it is *possible*
to write print-related code in python 2.6 that is also valid in python
3.

> if they were, then you wouldn't have to choose.

It seems to me you are arguing with the statement "Any print-related
python 2.6 code is valid python 3 code". Nobody is making this
statement. Let me repeat, what you should be arguing with is "It is
possible to write print-related python 2.6 code that is also valid
python 3 code". Perhaps I didn't make myself clear before, but at
least now I hope it's clear what I mean.

Cheers,
Daniel

> For example, it doesn't fix up 2.x code that prints tuples: incompatible, it
> will still execute but no longer do what it was supposed to do.
>
> But lest you focus down on that rare case, consider 2.x code that contains
>
> print "2+2", 2
>
> All such statements need to be fixed up in a 2->3 transition. Adding
> __future__
> just makes the code invalid, it doesn't give you any shred of compatibility
> for
> this. A code rewrite can be partially automated like 2to3 but the
> incompatibility needlessly introduces an additional set of things that Can
> Go
> Wrong(TM), and with Murphy present, as He always is, well.
>
>
>> So again, what sort of an incompatibility are you talking about
>> concerning 'print' between 2.6 and 3.x?
>
> Syntax and semantics. They're different.

Alf P. Steinbach

unread,
Jan 27, 2010, 12:29:25 PM1/27/10
to
* Daniel Fetchinson:

Perhaps we're in violent agreement. :-)

However, the root node of this subthread was my statement about the needless
incompatibility introduced by changing print in 3.x, whether that statement was
correct or reasonable / whatever.

The main problem with the incompatibility is for porting code, not for writing
code from scratch. It's also a problem wrt. learning the language. And I see no
good reason for it: print can't really do more, or less, or more conveniently
(rather, one has to write a bit more now for same effect).


Cheers,

- Alf

Luis M. González

unread,
Jan 27, 2010, 12:38:36 PM1/27/10
to
> Please don't post more noise and ad hominem attacks to the group, Steve.

"Ad hominem"?
Please, operor non utor lingua non notus per vulgaris populus.
Gratias ago vos...

Steve Holden

unread,
Jan 27, 2010, 12:50:10 PM1/27/10
to pytho...@python.org
Alf P. Steinbach wrote:
[...]

> The main problem with the incompatibility is for porting code, not for
> writing code from scratch. It's also a problem wrt. learning the
> language. And I see no good reason for it: print can't really do more,
> or less, or more conveniently (rather, one has to write a bit more now
> for same effect).

Of course it can do more: it allows you to layer your own print
functionality into the system much more easily than you could with the
print statement.

Alf P. Steinbach

unread,
Jan 27, 2010, 12:52:57 PM1/27/10
to
* Steve Holden:

> Alf P. Steinbach wrote:
> [...]
>> The main problem with the incompatibility is for porting code, not for
>> writing code from scratch. It's also a problem wrt. learning the
>> language. And I see no good reason for it: print can't really do more,
>> or less, or more conveniently (rather, one has to write a bit more now
>> for same effect).
>
> Of course it can do more: it allows you to layer your own print
> functionality into the system much more easily than you could with the
> print statement.

Yeah, point. Very minor though. :-)


Cheers,

- Alf

Grant Edwards

unread,
Jan 27, 2010, 3:05:35 PM1/27/10
to

I don't think it's minor at all. Being able to globally
redefine the behavior of "print" for all modules is a big win
when you want to import a module that's too chatty about what
it's doing. The "right" way for modules to chatter about
internals is using the logging module, but not everybody
follows that convention.

--
Grant Edwards grante Yow! Four thousand
at different MAGNATES, MOGULS
visi.com & NABOBS are romping in my
gothic solarium!!

Adam Tauno Williams

unread,
Jan 27, 2010, 3:28:34 PM1/27/10
to pytho...@python.org

So you get to determine that?

I'd call the whole print thing (a) a legitimate change to increase
consistency and (b) a fairly minor porting nuisance since application
code [as in big-chunks-o-code] almost never contains print statements.
I know at least two shops that have scripts they run on all Python code,
prior to it entering production, to ensure there are no print
statements.

Alf P. Steinbach

unread,
Jan 27, 2010, 4:50:28 PM1/27/10
to
* Adam Tauno Williams:

> On Wed, 2010-01-27 at 18:52 +0100, Alf P. Steinbach wrote:
>> * Steve Holden:
>>> Alf P. Steinbach wrote:
>>> [...]
>>>> The main problem with the incompatibility is for porting code, not for
>>>> writing code from scratch. It's also a problem wrt. learning the
>>>> language. And I see no good reason for it: print can't really do more,
>>>> or less, or more conveniently (rather, one has to write a bit more now
>>>> for same effect).
>>> Of course it can do more: it allows you to layer your own print
>>> functionality into the system much more easily than you could with the
>>> print statement.
>> Yeah, point. Very minor though. :-)
>
> So you get to determine that?

I'm sorry, I don't find that question meaningful.


> I'd call the whole print thing (a) a legitimate change to increase
> consistency and (b) a fairly minor porting nuisance since application
> code [as in big-chunks-o-code] almost never contains print statements.
> I know at least two shops that have scripts they run on all Python code,
> prior to it entering production, to ensure there are no print
> statements.


Considering that in your opinion "application code [as in big-chunks-o-code]
almost never contains print statements", is the point about being able to
replace print, as you see it, more than a minor point?


Cheers & sorry for not grokking your question,

- Alf

John Bokma

unread,
Jan 27, 2010, 6:03:12 PM1/27/10
to
Xah Lee <xah...@gmail.com> writes:

> Someone is badmouthing me, and it has been doing so over the years. I
> feel obliged to post a off topic relpy. See:
>
> • DreamHost.com and A Incidence of Harassment
> http://xahlee.org/Periodic_dosage_dir/t2/harassment.html

Dreamhost is not the only ISP that has agreed with me in the past
regarding your spamming. And yes, it's spamming if you copy paste an
article from your web site with the link to that site and cross post it
to as many groups as your Usenet provider allows for. Thank goodness
that GG has a limit on how many groups you can spam at a time.

Post to on-topic groups only, really on-topic groups, not as many as you
can select. And participate like you know do, and nobody will complain
about /how/ you post. And if you cross-post /set a follow-up-to/.

That's netiquette.

Jonathan Gardner

unread,
Jan 27, 2010, 6:51:15 PM1/27/10
to

My rough, machine-assisted translation:

"Don't try to use language that the people don't know. Thanks."

Jonathan Gardner

unread,
Jan 27, 2010, 6:54:23 PM1/27/10
to
On Jan 26, 10:12 pm, Steven D'Aprano

<ste...@REMOVE.THIS.cybersource.com.au> wrote:
>
> I did too, when I first heard cmp was to be dumped. But I changed my mind
> and now agree with the decision to drop cmp. Custom sorts are nearly
> always much better written with key rather than cmp: key adds an O(N)
> overheard to the sorting, while cmp makes sorting O(N**2). In other
> words, key is *much* faster, and generally easier to write as well.
>

Imagine what sort() could do if all the keys were platform-native
types. In other words, if you could bypass the Python compare because
all the keys were native int, char, char*, or float. You can't do that
with cmp either.

Paul Rubin

unread,
Jan 27, 2010, 6:54:55 PM1/27/10
to
Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> writes:
> always much better written with key rather than cmp: key adds an O(N)
> overheard to the sorting, while cmp makes sorting O(N**2).

Whaaaaaaaaaa ...... ???? No I don't think so.

Jonathan Gardner

unread,
Jan 27, 2010, 7:12:04 PM1/27/10
to

I think you missed the point about what a functional language is and
is not.

Let me see if I can help clear up that confusion a bit.

In a functional language, you don't use statements. For instance, when
you declare a new function, you call the function-declaring-function
with parameters describing the parameters and body of that function.

In such a language, flow control is very, very strange for those not
familiar with it. For instance, how can you call an "if" function that
only evaluates one or the other branches? In such a case, you're not
making a function call, at least not as you know it. What you're doing
is calling a special kind of function that doesn't evaluate its
parameters until later, if at all.

With the above paradigm, you have to start thinking about the
programming task in a completely different light. Rather than
organizing your code into a sequence of evaluated statements, you
organize it into one giant function that will evaluate its parameters
and return some result. This is a difficult paradigm for programmers
to grasp, and is one reason why Lisp and other functional languages
aren't know for being newbie-friendly.

Whether or not a statement can be used as an expression is really
orthogonal to this conversation.

If "yield", "break", and "continue" were functions, then you could
"call" them from within another function and have the call-ee yield,
break, or continue. For instance:

def do_something():
break()

while 1:
do_something()
# The next line is never reached
do_something_else()

This could be useful for some situations, but it is really, really
confusing and so it's not allowed. Such a function would have to rely
on some type of magic so that it is correctly identified as a yield,
break, or continue, and not a typical function call.

"import" is another case. It does something very special. It assigns
to values in the namespace of the code from which it was called. No
function can do that, at least not without some weird magic. It's
better to leave it as a statement and teach new users that it is very,
very special, than to redefine how functions work with the call-ees
namespace, or make it a common task to muck with such things.

If "while", "for", "try", "if", "def", and "class" were functions,
they would have to be written like so:

if(expr, if-true-expr, if-false-expr)

Note, however, that you can't execute if-true of if-false until AFTER
the if() function is called. That means either we re-define what it
means to call a function, or we have some notation that means "Don't
execute this yet". Either way, it's really, really confusing.

Also, note that statements allow you to combine many statements into
one. Python's rule is that you can't pass statements to a function,
only expression, so you'd have to re-define how that works to allow
some function that would combine multiple statements together.

In the end, print is a great candidate for a function, while the
others are most definitely not. Adding any of them as functions would
mean other, fundamental aspects of Python would have to be re-defined
as well.

I hope this clears up Steve's point about functional languages.

Jonathan Gardner

unread,
Jan 27, 2010, 7:16:59 PM1/27/10
to

You're referring to the O(N**2) bit, right? I am sure he knew it was O
(N*log(N)), which is still worse than O(N) for key.

If he didn't, well, Python has some fundamental flaws in its basic
sort algorithm.

Paul Rubin

unread,
Jan 27, 2010, 7:25:20 PM1/27/10
to
Jonathan Gardner <jgar...@jonathangardner.net> writes:
>> What about assert, import, and pass?
>...
> For instance, how can you call an "if" function ...
> If "yield", "break", and "continue" were functions, ...
> "import" ... does something very special. It assigns

> to values in the namespace of the code from which it was called.
> In the end, print is a great candidate for a function,

Reasonable point about import. "If", "yield", "break", and "continue"
are irrelevant if one accepts the flow control argument, although there
is already expression syntax for "if" and "yield". What about assert
and pass?

> Also, note that statements allow you to combine many statements into
> one. Python's rule is that you can't pass statements to a function,

But if we're going around introducing changes that break things, why not
get rid of that silly restriction?

I don't mind that 3.x is breaking stuff for the sake of improving
things. That's the whole idea of 3.x, after all. What bugs me is that
the improvements are mostly quite superficial, and the breakage seems
often gratuitous. I'd rather see much more drastic changes and
correspondingly much larger improvements.

Right now I rent an apartment in a city where real estate values have
dropped a couple percent in the past few years. So in principle, I
could move to a 2% bigger apartment while paying the same rent, or move
to a similarly sized apartment while paying 2% less. Either of those is
objectively an improvement, but am I going to do it? Hell no--moving
even down the same street is way too big a hassle to even consider doing
it for such a tiny gain. But if the "2%" were replaced by 3x or 5x, the
proposition would be a heck of a lot more attractive, even if I had to
move a larger distance. That's sort of the way I feel about switching
from Python 2.x to 3.x.

Paul Rubin

unread,
Jan 27, 2010, 7:30:40 PM1/27/10
to
Jonathan Gardner <jgar...@jonathangardner.net> writes:
> You're referring to the O(N**2) bit, right? I am sure he knew it was O
> (N*log(N)), which is still worse than O(N) for key.

It's O(n log n) for both key and cmp. key is usually more convenient
and usually gives a constant-factor speedup (DSU pattern), but it uses
more memory and there are some types of orderings that it can't handle
without a bunch of contortion.

Carl Banks

unread,
Jan 27, 2010, 7:44:18 PM1/27/10
to
On Jan 27, 4:16 pm, Jonathan Gardner <jgard...@jonathangardner.net>
wrote:

Quicksort is O(N**2) worst case, perhaps that's what he meant. I'm
not sure about timsort but since it's based on quicksort I'd guess it
is O(N**2) or worse, worst case, as well.

Typical case of a sort is still O(N*log(N)) whether using key or cmp.
People recommended against cmp not because of overall algorithmic time
considerations, but because of the number of function calls. cmp
function was called a minimum of N-1 times and typically around N*log2
(N) times, whereas key was called exactly N times. Since the overhead
of a Python function call was very large compared to the built-in cmp
operation, it usually outweighed the algorithmic time considerations.


Carl Banks

Steven D'Aprano

unread,
Jan 27, 2010, 7:47:41 PM1/27/10
to
On Wed, 27 Jan 2010 18:29:25 +0100, Alf P. Steinbach wrote:

> The main problem with the incompatibility is for porting code, not for
> writing code from scratch.

Correct. It's a trivial problem, but still a problem.

> It's also a problem wrt. learning the language.

This makes no sense. Why is it harder to learn

print(x, y, z)

than this?

print x, y, z

The first case is like the other functions you have to learn, like len().
In fact, many newbies to Python put unneeded parentheses around arguments
to print simply because they assume it is a function.

I would argue that the new print function is *simpler* to learn. It is
more consistent with other built-ins, and has fewer magic idioms to
learn. Instead of:

print >>fileObj, x, y, z

you use regular function syntax with a meaningful keyword:

print(x, y, z, file=fileObj)

If you want suppress the newline at the end of each print:

print x, y, z, # note the final comma

compared to:

print(x, y, z, end='')

If you want to change the space between elements, instead of:

sys.stdout.write(str(x) + "*" + str(y) + "*" + str(z) + '\n')

you use:

print(x, y, z, sep='*')


If you want to override the behaviour of print in a module, instead of
having to edit the source code of the module (which might not even be
available), all you need to do is monkey-patch it:

import module
module.print = myprint

--
Steven

Steven D'Aprano

unread,
Jan 27, 2010, 8:09:58 PM1/27/10
to
On Wed, 27 Jan 2010 00:36:52 -0800, Paul Rubin wrote:

> Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> writes:

>> Without becoming a purely functional language, you won't get rid of all
>> statements.
>
> Why not? GCC lets you use any statement in an expression:

I stand corrected. Whether it is a good idea or not is another story.

>> for, while, if, try, break, yield, return are all used for flow
>> control, and should remain as statements.
>

> What about assert, import, and pass?

Both assert and pass are special and need to be treated specially by the
compiler. Arguably we could replace pass with None, but pass makes the
intent more obvious.

Although assert could be a function, it is treated specially by the
compiler and so making it a statement emphases that it is special.

The regular form of import could easily be a function returning the
module object. After all, that's exactly what __import__ is! But using
__import__ for anything but the simplest cases is quite awkward, hence we
have syntactic sugar in the form of the import statement.

You also missed del as another statement-based command.

All the current statements have good strong reasons for being statements.
print on the other hand lacks a strong reason for being a statement, and
the only good argument against changing is to avoid an incompatible
change. But since it is not a gratuitous incompatible change, the long
term benefit out-weighs the short-term pain, in my opinion.


--
Steven

Steven D'Aprano

unread,
Jan 27, 2010, 8:44:48 PM1/27/10
to


I may have the details wrong, but the performance of sort with cmp is
very poor.

sort with key calls the key function once for each element in the list,
which is O(N), and then sorts O(N*log N), giving a total of O(N*log N).

sort with cmp has to compare the comparison function multiple times for
each element. I *thought* it ended up calling it N times each, giving
O(N**2), but I may be delusional. Whatever it is though, it's quite slow.
Here's my test code (for Python 2.5):

from timeit import Timer
from string import letters
from random import shuffle

def mycmp(s, t):
return cmp(s.upper(), t.upper())

def randstr():
L = list(letters)
shuffle(L)
return ''.join(L)

setup = "from __main__ import mycmp, data"

N = 300
data = [randstr() for _ in xrange(N)]
t1 = Timer("d = data[:]; d.sort()", setup) # raw sort
t2 = Timer("d = data[:]; d.sort(cmp=mycmp)", setup)
t3 = Timer("d = data[:]; d.sort(key=str.upper)", setup)

for t in (t1, t2, t3):
print min(t.repeat(number=500))

N *= 10 # Do it again with bigger N.
data = [randstr() for _ in xrange(N)]
for t in (t1, t2, t3):
print min(t.repeat(number=500))

And here are the results on my PC:

# N = 300
0.0631489753723
2.36756515503
0.226485967636

# N = 3000
1.03457903862
35.3092911243
2.77242517471

This doesn't support my claim of O(N**2), but it does demonstrate that
sort with cmp should be avoided if at all possible.

--
Steven

Steven D'Aprano

unread,
Jan 27, 2010, 8:56:00 PM1/27/10
to
On Wed, 27 Jan 2010 16:44:18 -0800, Carl Banks wrote:

>> You're referring to the O(N**2) bit, right? I am sure he knew it was O
>> (N*log(N)), which is still worse than O(N) for key.
>>
>> If he didn't, well, Python has some fundamental flaws in its basic sort
>> algorithm.
>
> Quicksort is O(N**2) worst case, perhaps that's what he meant.

No, apparently I was delusional.


> I'm not
> sure about timsort but since it's based on quicksort I'd guess it is
> O(N**2) or worse, worst case, as well.

timsort is actually a mergesort, not a quicksort.

You may like to read this:

http://svn.python.org/projects/python/trunk/Objects/listsort.txt


> Typical case of a sort is still O(N*log(N)) whether using key or cmp.
> People recommended against cmp not because of overall algorithmic time
> considerations, but because of the number of function calls. cmp
> function was called a minimum of N-1 times and typically around N*log2
> (N) times, whereas key was called exactly N times. Since the overhead
> of a Python function call was very large compared to the built-in cmp
> operation, it usually outweighed the algorithmic time considerations.

Yes, that sounds more like it. Thanks for the corrections.


--
Steven

David Cournapeau

unread,
Jan 27, 2010, 10:27:41 PM1/27/10
to pytho...@python.org
On Thu, Jan 28, 2010 at 9:25 AM, Paul Rubin <no.e...@nospam.invalid> wrote:

> I don't mind that 3.x is breaking stuff for the sake of improving
> things.  That's the whole idea of 3.x, after all.  What bugs me is that
> the improvements are mostly quite superficial, and the breakage seems
> often gratuitous.  I'd rather see much more drastic changes and
> correspondingly much larger improvements.

At the risk of saying something trivial, that depends on what you
consider superficial or not. It totally depends on your usage. I know
I would have taken something to improve python packaging (dropping
distutils, stable ABI across the whole 3.x range) over any feature in
py3k.

That's why your real estate comparison is not adequate IMHO - what is
2 % for you is maybe 30 % for someone else, and my own 30 % for
packaging may be 1 % for most people who don't care about C extensions
at all.

David.

Gib Bogle

unread,
Jan 27, 2010, 11:03:14 PM1/27/10
to

"ad hominem" is "lingua notus per vulgaris populus", the vulgar pop of these
parts, anyway.

Gib Bogle

unread,
Jan 27, 2010, 11:04:27 PM1/27/10
to
Steven D'Aprano wrote:

> On Wed, 27 Jan 2010 02:28:00 +0100, Alf P. Steinbach wrote:
>
>>>> * Print is now a function. Great, much improvement.
>> Actually not, IMHO. All it does is is to provide incompatibility. They
>> forgot Ronald Reagan's old maxim: if it don't need fixin', don't fix it.

The aphorism needs fixing: If it ain't broke, don't fix it.

Jonathan Gardner

unread,
Jan 28, 2010, 2:50:55 AM1/28/10
to
On Jan 27, 4:25 pm, Paul Rubin <no.em...@nospam.invalid> wrote:
> What about assert and pass?
>

If you're going to have statements, you're going to need the null
statement. That's "pass". It could be renamed "null_statement" but
"pass" is a better description. "None" and "pass" are cousins of
sorts, since "None" is the null expression and "pass" the null
statement.

I agree on "assert". I don't like running a program in test mode and
then running it in production mode with different code. I would rather
test what I am going to actually run. "assert" should be a function,
and support for removing assert statements should be eliminated. I
simply don't use assert statements at all.

Paul Rubin

unread,
Jan 28, 2010, 3:37:54 AM1/28/10
to
Jonathan Gardner <jgar...@jonathangardner.net> writes:
> If you're going to have statements, you're going to need the null
> statement. That's "pass".

Why? Expressions are statements, so you could just say "pass" (in
quotes, denoting a string literal), or 0, or None, os anything else like
that, instead of having a special statement.

Alf P. Steinbach

unread,
Jan 28, 2010, 4:12:18 AM1/28/10
to
* Steven D'Aprano:

> On Wed, 27 Jan 2010 18:29:25 +0100, Alf P. Steinbach wrote:
>
>> The main problem with the incompatibility is for porting code, not for
>> writing code from scratch.
>
> Correct. It's a trivial problem, but still a problem.
>
>> It's also a problem wrt. learning the language.
>
> This makes no sense. Why is it harder to learn
>
> print(x, y, z)
>
> than this?
>
> print x, y, z

I think it's actually easier to learn just the 3.x form.

But it's more difficult to learn that there are /two different/ syntactic forms,
depending on which version of Python you're using and in addition depending on
__future__ declarations!

E.g., picking up some example code from the web, and it does not work...


> The first case is like the other functions you have to learn, like len().
> In fact, many newbies to Python put unneeded parentheses around arguments
> to print simply because they assume it is a function.
>
> I would argue that the new print function is *simpler* to learn. It is
> more consistent with other built-ins, and has fewer magic idioms to
> learn.

Yes, yes, yes, I agree.


> Instead of:
>
> print >>fileObj, x, y, z
>
> you use regular function syntax with a meaningful keyword:
>
> print(x, y, z, file=fileObj)
>
> If you want suppress the newline at the end of each print:
>
> print x, y, z, # note the final comma
>
> compared to:
>
> print(x, y, z, end='')

Actually I thought the final comma thing was nice. It was like Basic. I think
the 2.x 'print' must have been modeled on Basic's 'print'.


> If you want to change the space between elements, instead of:
>
> sys.stdout.write(str(x) + "*" + str(y) + "*" + str(z) + '\n')
>
> you use:
>
> print(x, y, z, sep='*')
>
>
> If you want to override the behaviour of print in a module, instead of
> having to edit the source code of the module (which might not even be
> available), all you need to do is monkey-patch it:
>
> import module
> module.print = myprint

>>> import builtins
>>>
>>> org_print = print
>>> builtins.print = 666
>>>
>>> print( "trallala" )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
>>> org_print( "but is that really so smart?" )
but is that really so smart?
>>> _


Cheers,

- Alf

Mitchell L Model

unread,
Jan 28, 2010, 11:03:20 AM1/28/10
to pytho...@python.org
I have been working with Python 3 for over a year. I used it in
writing my book "Bioinformatics Programming Using Python" (http://oreilly.com/catalog/9780596154509
). I didn't see any point in teaching an incompatible earlier version
of a language in transition. In preparing the book and its examples I
explored a large number of Python modules in some depth and
encountered most of the differences between the language and libraries
of Python 2 and Python 3. The change was a bit awkward for a while,
and there were some surprises, but in the end I have found nothing in
Python 3 for which I would prefer Python 2's version.

Removal of old-style classes is a big win. Having print as a function
provides a tremendous amount of flexibility. I use the sep and end
keywords all the time. There is no reason for print to be a statement,
and it was an awkward inconsistency in a language that leans towards
functional styles. Likewise the elimination of cmp, while shocking,
leads to much simpler comparison arguments to sort, since all the
function does is return a key; then, sort uses __lt__ (I think) so it
automatically uses each class's definition of that. The weird objects
returned from things like sorted, dict.keys/values/items, and so on
are values that in practice are used primarily in iterations; you can
always turn the result into a list, though I have to admit that while
developing and debugging I trip trying to pick out a specific element
from one of these using indexing (typically [0]); I've learned to
think of them as generators, even though they aren't. The
rearrangements and name changes in the libraries are quite helpful. I
could go on, but basically the language and library changes are on the
whole large improvements with little, if any, downside.

Conversion of old code is greatly facilitied by the 2to3 tool that
comes with Python 3. The big issue in moving from 2 to 3 is the
external libraries and development tools you use. Different IDEs have
released versions that support Python 3 at different times. (I believe
Wing was the first.) If you use numpy, for example, or one of the many
libraries that require it, you are stuck. Possibly some important
facilities will never be ported to Python 3, but probably most active
projects will eventually produce a Python 3 version -- for example,
according to its web page, a Python 3 version of PIL is on the way. I
was able to cover all the topics in my book using only Python library
modules, something I felt would be best for readers -- I used
libraries such as elementree, sqlite3, and tkinter. The only
disappointment was that I couldn't include a chapter on BioPython,
since there is no Python 3 version.

By now, many large facilities support both Python 2 and Python 3. I am
currently building a complex GUI/Visualization application based on
the Python 3 version of PyQt4 and Wing IDE and am delighted with all
of it. It may well be that some very important large

Roy Smith

unread,
Jan 28, 2010, 11:09:58 AM1/28/10
to
In article <mailman.1545.1264694...@python.org>,

Mitchell L Model <MLM...@Comcast.net> wrote:

> I use the sep and end keywords all the time.

What are 'sep' and 'end'? I'm looking in
http://docs.python.org/3.1/genindex-all.html and don't see those mentioned
at all. Am I just looking in the wrong place?

Alf P. Steinbach

unread,
Jan 28, 2010, 11:13:22 AM1/28/10
to
* Roy Smith:

>>> print( print.__doc__ )
print(value, ..., sep=' ', end='\n', file=sys.stdout)

Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
>>> _


Cheers & hth.,

- Alf

Lie Ryan

unread,
Jan 28, 2010, 11:35:36 AM1/28/10
to

or, if the null statement "pass" is removed, you could define:
pass = None
or
pass = object() # sentinel

and have essentially the same thing.

hmm... on second thought, not special-casing pass means doing a
LOAD_GLOBAL or LOAD_CONST for operation that is supposed to be doing
nothing.

Lie Ryan

unread,
Jan 28, 2010, 11:54:26 AM1/28/10
to
On 01/28/10 20:12, Alf P. Steinbach wrote:
> * Steven D'Aprano:
>> On Wed, 27 Jan 2010 18:29:25 +0100, Alf P. Steinbach wrote:>
>> Instead of:
>>
>> print >>fileObj, x, y, z
>>
>> you use regular function syntax with a meaningful keyword:
>>
>> print(x, y, z, file=fileObj)
>>
>> If you want suppress the newline at the end of each print:
>>
>> print x, y, z, # note the final comma
>>
>> compared to:
>>
>> print(x, y, z, end='')
>
> Actually I thought the final comma thing was nice. It was like Basic. I
> think the 2.x 'print' must have been modeled on Basic's 'print'.

if that was true, then python missed the final semicolon

>> If you want to change the space between elements, instead of:
>>
>> sys.stdout.write(str(x) + "*" + str(y) + "*" + str(z) + '\n')
>>
>> you use:
>>
>> print(x, y, z, sep='*')
>>
>>
>> If you want to override the behaviour of print in a module, instead of
>> having to edit the source code of the module (which might not even be
>> available), all you need to do is monkey-patch it:
>>
>> import module
>> module.print = myprint
>
> >>> import builtins
> >>>
> >>> org_print = print
> >>> builtins.print = 666
> >>>
> >>> print( "trallala" )
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> TypeError: 'int' object is not callable
> >>> org_print( "but is that really so smart?" )
> but is that really so smart?
> >>> _

Monkey patching follows (or should follow) the same rule as class
inheritance overriding: the overrider's input domain must be a superset
of the overriden's input domain and the overrider's output range must be
a subset of the overriden's output range. 666 object (int) is not even
remotely compatible with function object.

Alf P. Steinbach

unread,
Jan 28, 2010, 12:37:56 PM1/28/10
to
* Lie Ryan:

Yes, that's my point.

A 'print' replacement should ideally provide all the guarantees on behavior that
standard 'print' does.

And with that it's not so easy to put in a /correct/ replacement of 'print'; in
particular, it has to honor the 'file' keyword argument.

Thus the 3.x design makes it easy to replace 'print' incorrectly.

I'd rather still had 'print' as keyword... ;-)


Cheers,

- Alf

Terry Reedy

unread,
Jan 28, 2010, 1:20:02 PM1/28/10