Python's "only one way to do it" philosophy isn't good?

J

John Nagle

Josiah said:
....

I would guess it is because some other data types may have side-effects.
On the other hand, a peephole optimizer could be written to trim out
unnecessary LOAD_CONST/POP_TOP pairs.


Obviously dead code removal happens regardless of optimization level in
current Pythons.


Constant folding happens regardless of optimization level in current
Pythons.
So really, assert and docstring removals. Eh.

It's hard to optimize Python code well without global analysis.
The problem is that you have to make sure that a long list of "wierd
things", like modifying code or variables via getattr/setattr, aren't
happening before doing significant optimizations. Without that,
you're doomed to a slow implementation like CPython.

ShedSkin, which imposes some restrictions, is on the right track here.
The __slots__ feature is useful but doesn't go far enough.

I'd suggest defining "simpleobject" as the base class, instead of "object",
which would become a derived class of "simpleobject". Objects descended
directly from "simpleobject" would have the following restrictions:

- "getattr" and "setattr" are not available (as with __slots__)
- All class member variables must be initialized in __init__, or
in functions called by __init__. The effect is like __slots__,
but you don't have to explictly write declarations.
- Class members are implicitly typed with the type of the first
thing assigned to them. This is the ShedSkin rule. It might
be useful to allow assignments like

self.str = None(string)

to indicate that a slot holds strings, but currently has the null
string.
- Function members cannot be modified after declaration. Subclassing
is fine, but replacing a function member via assignment is not.
This allows inlining of function calls to small functions, which
is a big win.
- Private function members (self._foo and self.__foo) really are
private and are not callable outside the class definition.

You get the idea. This basically means that "simpleobject" objects have
roughly the same restrictions as C++ objects, for which heavy compile time
optimization is possible. Most Python classes already qualify for
"simpleobject". And this approach doesn't require un-Pythonic stuff like
declarations or extra "decorators".

With this, the heavy optimizations are possible. Strength reduction. Hoisting
common subexpressious out of loops. Hoisting reference count updates out of
loops. Keeping frequently used variables in registers. And elimination of
many unnecessary dictionary lookups.

Python could get much, much faster. Right now CPython is said to be 60X slower
than C. It should be possible to get at least an order of magnitude over
CPython.

John Nagle
 
T

Terry Reedy

| > Terry Reedy wrote:
| > > In Python, you have a choice of recursion (normal or tail)

[snip Stroud questions]

| I'm afraid Terry is wrong here, at least if he meant that CPython had
| tail recursion *optimization*.

NO!!!
I did not mean that or imply that in any way.

| (and just for those who don't know yet, it's not a shortcoming, it's a
| design choice.)

And I already noted in a followup that I am working on a Python Papers
paper explaining that choice, including Guido's claim that 'for statements
are better'.

So frankly I am a little annoyed that you dragged my name into your answer
to Stroud when you should have succintly said 'No, Never', or better,
nothing at all, as someone else already did say that. Read more of the
tread before jumping in and acribing ignorance to people.

Terry Jan Reedy
 
A

Alexander Schmolck

Steven D'Aprano said:
Do you mean you don't believe the decision was made, or you don't agree
with the decision?

Neither. I don't believe the rationale stated in this thread to be the true
reason.
Are you volunteering? If you are, I'm sure your suggestion will be welcomed
gratefully.

I rather doubt it. Guido has stated quite clearly that his not interested in
incorporating this feature.
If we can live with a certain amount of "arbitrary failures" in simple
arithmetic,

I prefer not too, and thus when possible avoid to use languages where ``a +
b`` is liable to fail arbitrarily (such as C, where the behavior will often be
undefined).
then the world won't end if tail recursion isn't optimized away by the
compiler.

I'd personally much rather have arithmetic working properly. Unfortunately
this is not an option at the moment, although quite a few smart people are
working on it and although it is an immensely costly problem.
You can always hand-optimize it yourself.

Not tail calls, in general, no.

'as
 
P

Paul Rubin

Steven D'Aprano said:
Sorry, how does that work? You're suggesting that there is an algorithm
which the compiler could follow to optimize away tail-recursion, but human
beings can't follow the same algorithm?

Now I'm confused.

The usual compiler method is to translate the code into
continuation-passing style and thereby gain tail-recursion
optimization automagically. Of course a human could do the same thing
in principle, but it would result in insanely difficult-to-write,
unreadable and unmaintainable code. At a higher level, there are no
Python features whatsoever, either existing or proposed, that couldn't
be eliminated and left to the human. Iterators? While loops? Who
needs 'em? We could all go back to programming in machine code. But
Python is supposed to make programming easier, not harder.
 
K

Kay Schluehr

To the extent that some of these optimizations could
be achieved by writing better Python code, it would
nice for optimization tools to have a "suggest" mode.

Is anyone out there who uses MS Word and doesn't deactivate the
"suggest" mode i.e. Clippy? Maybe someone shall write a lucid blog
entry about the failure of "suggest" modes in general or point me to
one. Autocompletion as a typing aid might be considered as a counter
example but only because you don't really have a choice and will not
be confronted with nonsensical AI guesses.
 
S

Steven D'Aprano

Neither. I don't believe the rationale stated in this thread to be the true
reason.


Don't keep us in suspense. What do you believe is the true reason?

I rather doubt it. Guido has stated quite clearly that his not
interested in incorporating this feature.

He's not the only one who gets to make these decisions. But even if he
uses his veto to prevent tail-recursion optimization from being put into
the main branch, there are other options.


I prefer not too, and thus when possible avoid to use languages where
``a + b`` is liable to fail arbitrarily (such as C, where the behavior
will often be undefined).

That's not the sort of arbitrary failure I was discussing, but for that
matter Python is one of those languages. Perhaps Python is not the
language for you?

Correct me if I'm wrong, but surely it is C++ that can have arbitrary
behaviour for "a + b", not C?


I'd personally much rather have arithmetic working properly.
Unfortunately this is not an option at the moment, although quite a few
smart people are working on it and although it is an immensely costly
problem.


Not tail calls, in general, no.

Sorry, how does that work? You're suggesting that there is an algorithm
which the compiler could follow to optimize away tail-recursion, but human
beings can't follow the same algorithm?

Now I'm confused.
 
J

Josiah Carlson

John said:
Josiah Carlson wrote: [snip]
Constant folding happens regardless of optimization level in current
Pythons.
So really, assert and docstring removals. Eh.

It's hard to optimize Python code well without global analysis.
The problem is that you have to make sure that a long list of "wierd
things", like modifying code or variables via getattr/setattr, aren't
happening before doing significant optimizations. Without that,
you're doomed to a slow implementation like CPython.

ShedSkin, which imposes some restrictions, is on the right track here.
The __slots__ feature is useful but doesn't go far enough. [snip]
Python could get much, much faster. Right now CPython is said to be 60X
slower
than C. It should be possible to get at least an order of magnitude over
CPython.

Don't get me wrong; I'm all for adding optimizations, I was merely
expressing that currently, 'python -OO' doesn't really do a whole lot.
I've a long-time user of psyco, have mucked about with
scipy.weave.inline, and have been a heavy user of Pyrex and C. If there
was a method of offering some simple optimization cues to the Python
runtime to improve its speed, I would be happy to add them when I really
care about speed (I already do more than that when writing Pyrex). The
real question is whether we can get a practical implementation of these
optimizations as easy to use as psyco.


- Josiah
 
J

Josiah Carlson

Paul said:
The usual compiler method is to translate the code into
continuation-passing style and thereby gain tail-recursion
optimization automagically. Of course a human could do the same thing
in principle, but it would result in insanely difficult-to-write,
unreadable and unmaintainable code. At a higher level, there are no
Python features whatsoever, either existing or proposed, that couldn't
be eliminated and left to the human. Iterators? While loops? Who
needs 'em? We could all go back to programming in machine code. But
Python is supposed to make programming easier, not harder.

Thanks to Richie Hindle, there exists a goto for Python implementation
that makes such things quite trivial (assuming one doesn't like
"abusing" break/continue/else). http://entrian.com/goto/ (which, by
the way, is the best April-fools joke ever)


- Josiah
 
D

Diez B. Roggisch

It's hard to optimize Python code well without global analysis.
The problem is that you have to make sure that a long list of "wierd
things", like modifying code or variables via getattr/setattr, aren't
happening before doing significant optimizations. Without that,
you're doomed to a slow implementation like CPython.

ShedSkin, which imposes some restrictions, is on the right track here.
The __slots__ feature is useful but doesn't go far enough.

I'd suggest defining "simpleobject" as the base class, instead of
"object",
which would become a derived class of "simpleobject". Objects descended
directly from "simpleobject" would have the following restrictions:

- "getattr" and "setattr" are not available (as with __slots__)
- All class member variables must be initialized in __init__, or
in functions called by __init__. The effect is like __slots__,
but you don't have to explictly write declarations.
- Class members are implicitly typed with the type of the first
thing assigned to them. This is the ShedSkin rule. It might
be useful to allow assignments like

self.str = None(string)

to indicate that a slot holds strings, but currently has the null
string.
- Function members cannot be modified after declaration. Subclassing
is fine, but replacing a function member via assignment is not.
This allows inlining of function calls to small functions, which
is a big win.
- Private function members (self._foo and self.__foo) really are
private and are not callable outside the class definition.

You get the idea. This basically means that "simpleobject" objects have
roughly the same restrictions as C++ objects, for which heavy compile time
optimization is possible. Most Python classes already qualify for
"simpleobject". And this approach doesn't require un-Pythonic stuff like
declarations or extra "decorators".

With this, the heavy optimizations are possible. Strength reduction.
Hoisting
common subexpressious out of loops. Hoisting reference count updates
out of
loops. Keeping frequently used variables in registers. And elimination of
many unnecessary dictionary lookups.


I won't give you the "prove it by doing it"-talk. It's to cheap.

Instead I'd like to say why I don't think that this will buy you much
performance-wise: it's a local optimization only. All it can and will do
is to optimize lookups and storage of attributes - either functions or
values - and calls to methods from within one specialobject. As long as
expressions stay in their own "soup", things might be ok.

The very moment you mix this with "regular", no-strings-attached python
code, you have to have the full dynamic machinery in place + you need
tons of guarding statements in the optimized code to prevent access
violations.

So in the end, I seriously doubt the performance gains are noticable.
Instead I'd rather take the pyrex-road, which can go even further
optimizing with some more declarations. But then I at least know exactly
where the boundaries are. As does the compiler.
Python could get much, much faster. Right now CPython is said to be 60X
slower
than C. It should be possible to get at least an order of magnitude over
CPython.


Regardless of the possibility of speeding it up - why should one want
this? Coding speed is more important than speed of coding in 90%+ of all
cases. The other ones - well, if you _really_ want speed, assembler is
the way to go. I'm serious about that. There is one famous mathematical
library author that does code in assembler - because in the end, it's
all about processor architecture and careful optimization for that. [1]

The same is true for e.g. the new Cell architecture, or the
altivec-optimized code in photoshop that still beats the crap out of
Intel processors on PPC-machines.

I'm all for making python faster if it doesn't suffer
functionality-wise. But until there is a proof that something really
speeds up python w/o crippling it, I'm more than skeptical.

Diez

[1] http://math-atlas.sourceforge.net/faq.html#auth

"""
Kazushige Goto
His ev5/ev6 GEMM is used directly by ATLAS if the user answers
"yes" to its use during the configuration procedure on an alpha
processor. This results in a significant speedup over ATLAS's own GEMM
codes, and is the fastest ev5/ev6 implementation we are aware of.
"""
 
B

Bruno Desthuilliers

Terry Reedy a écrit :
| > Terry Reedy wrote:
| > > In Python, you have a choice of recursion (normal or tail)

[snip Stroud questions]

| I'm afraid Terry is wrong here, at least if he meant that CPython had
| tail recursion *optimization*.

NO!!!
I did not mean that or imply that in any way.

I understand you didn't mean it, but since the whole point of
tail-recursion is allowing optimisation (else tail-recursion is nothing
else than a subset of recursion), you somehow implied it, even while
that was not your intention.
| (and just for those who don't know yet, it's not a shortcoming, it's a
| design choice.)

And I already noted in a followup that I am working on a Python Papers
paper explaining that choice, including Guido's claim that 'for statements
are better'.

So frankly I am a little annoyed that you dragged my name into your answer
to Stroud when you should have succintly said 'No, Never', or better,
nothing at all, as someone else already did say that. Read more of the
tread before jumping in and acribing ignorance to people.

You're right on the fact that I should have read more of the thread
before posting this (which I usually do), and I do apologize for this.
But please note the second half of the sentence - which puts a strong
precondition on the validity of the first part.
 
A

Antoon Pardon

| I've just read an article "Building Robust System" by Gerald Jay
| Sussman. The article is here:
|
http://swiss.csail.mit.edu/classes/symbolic/spring07/readings/robust-systems.pdf
|
| In it there is a footprint which says:
| "Indeed, one often hears arguments against building exibility into an
| engineered sys-
| tem. For example, in the philosophy of the computer language Python it
| is claimed:

For him to imply that Python is anti-flexibility is wrong. Very wrong..
He should look in a mirror. See below.

My impression is that python supporters often enough show
some anti-flexibility attitude.
| \There should be one|and preferably only one|obvious way to do
| it."[25] Science does
| not usually proceed this way: In classical mechanics, for example, one
| can construct equa-
| tions of motion using Newtonian vectoral mechanics, or using a
| Lagrangian or Hamiltonian
| variational formulation.[30] In the cases where all three approaches
| are applicable they are
| equivalent, but each has its advantages in particular contexts."

And in those contexts, one would hope that the method with advantages is
somehow the obvious way to do it. Otherwise beginners might become like
Buriden's ass.

So I dispute that science is as different as he claims. And I do not see
any real value in the statement in that I do not see it saying anything
useful to the reader, at least not in this snippet.

Yes science is different. The difference is the following. Should
science only know the Newtonian vectoral mechanics and someone
would come up with the Lagrangian approach, nobody would protest
against this new approach by remarking that there should only be
one obvious approach, implying that by introducing the second approach
you give the people a choice, which they will have to think about
so their decision what to use is no longer obvious, which it is
if there is only one option.

Yet these kind of remarks are made often enough when someone suggest a
change to python.
 
J

John Nagle

Diez said:
Regardless of the possibility of speeding it up - why should one want
this? Coding speed is more important than speed of coding in 90%+ of all
cases.

When you have to start buying more servers for the server farm,
it's a real pain. I'm actually facing that because Python's HTML
parsing is so slow.

John Nagle
 
T

Terry Reedy

|> | > Terry Reedy wrote:
|> | > > In Python, you have a choice of recursion (normal or tail)

Bruno
| I'm afraid Terry is wrong here, at least if he meant that CPython had
| tail recursion *optimization*.

| Terry Reedy a écrit :
| > NO!!!
| > I did not mean that or imply that in any way.

Bruno
| I understand you didn't mean it, but since the whole point of
| tail-recursion is allowing optimisation

Wrong again. That is a reason, even a primary reason, for some people some
of the time, but not at all the only reason anyone would ever write linear
recursion in tail rather than body (my term) form. So nothing follows from
this false premise.

| (else tail-recursion is nothing else than a subset of recursion)

So? Body-recursion (non-tail-recursion) is also nothing else than a subset
of recursion.

| you somehow implied it, even while that was not your intention.

False in its own right. Any langauge that allow recursion allows the
subset that happen to constitute tail recursion. Most do not *mandate*
that compilers specially recognize and optimize that subset. So there is
pragmatically no implication that the latter follows from the former.

The reason I specifically mentioned tail recursion is because Prof.
Sussman, who complained about
There should be one-- and preferably only one --obvious way to do it.
-- to quote Brother Tim accurately -- co-developed Scheme. To me, Scheme
promotes tail recursion as the one true way as much or more as anything is
similarly promoted in Python. That mention had nothing in itself to do
with the separate issue of optimizing tail calls.

What Sussman apparently missed is that Tim's main point is that there
should be some rather than no obvious way to do things. The parenthetical
optional secondary desiderata is just that -- optional and secondary.

Terry Jan Reedy
 
T

Terry Reedy

| > For him to imply that Python is anti-flexibility is wrong. Very
wrong..
| > He should look in a mirror. See below.
|
| My impression is that python supporters often enough show
| some anti-flexibility attitude.

More so than supporters of most other languages, in particular Scheme?

Here's the situation. Python is making inroads at MIT, Scheme home turf.
The co-developer of Scheme, while writing about some other subject, tosses
in an off-the-wall slam against Python. Someone asks what we here think.
I think that the comment is a crock and the slam better directed, for
instance, at Scheme itself. Hence 'he should look in a mirror'.

| Yes science is different. The difference is the following. Should
| science only know the Newtonian vectoral mechanics and someone
| would come up with the Lagrangian approach, nobody would protest
| against this new approach by remarking that there should only be
| one obvious approach,

The history of science is a history of innovation and resistance to
innovation. Do you have information that the introduction of the
Lagrangian approach was exceptional? Do you really think that no college
student has ever groused about having to learn another approach that is
only equivalent to what he already knows?

| Yet these kind of remarks are made often enough when someone suggest a
| change to python.

So? Tim wrote 'There should be one-- and preferably only one --obvious way
to do it'. The primary clause is that there should at least one. The
secondary clause is that once there is a good and obvious way to do
something, we take a hard look before adding another. As it is, there are
already multiple ways to do many things. And there are probably at least
10 suggested innovations for everyone accepted.

tjr
 
A

Aahz

| Terry Reedy wrote:
| > In Python, you have a choice of recursion (normal or tail)
|
| Please explain this.

I am working on a paper for Python Papers that will. It was inspired by
the question 'why doesn't Python do tail-recursion optimization'.

....with the proof contained in the margins?
 
M

Michele Simionato

It's hard to optimize Python code well without global analysis.
The problem is that you have to make sure that a long list of "wierd
things", like modifying code or variables via getattr/setattr, aren't
happening before doing significant optimizations. Without that,
you're doomed to a slow implementation like CPython.

ShedSkin, which imposes some restrictions, is on the right track here.
The __slots__ feature is useful but doesn't go far enough.

I'd suggest defining "simpleobject" as the base class, instead of "object",
which would become a derived class of "simpleobject". Objects descended
directly from "simpleobject" would have the following restrictions:

- "getattr" and "setattr" are not available (as with __slots__)
- All class member variables must be initialized in __init__, or
in functions called by __init__. The effect is like __slots__,
but you don't have to explictly write declarations.
- Class members are implicitly typed with the type of the first
thing assigned to them. This is the ShedSkin rule. It might
be useful to allow assignments like

self.str = None(string)

to indicate that a slot holds strings, but currently has the null
string.
- Function members cannot be modified after declaration. Subclassing
is fine, but replacing a function member via assignment is not.
This allows inlining of function calls to small functions, which
is a big win.
- Private function members (self._foo and self.__foo) really are
private and are not callable outside the class definition.

You get the idea. This basically means that "simpleobject" objects have
roughly the same restrictions as C++ objects, for which heavy compile time
optimization is possible. Most Python classes already qualify for
"simpleobject". And this approach doesn't require un-Pythonic stuff like
declarations or extra "decorators".

With this, the heavy optimizations are possible. Strength reduction. Hoisting
common subexpressious out of loops. Hoisting reference count updates out of
loops. Keeping frequently used variables in registers. And elimination of
many unnecessary dictionary lookups.

Python could get much, much faster. Right now CPython is said to be 60X slower
than C. It should be possible to get at least an order of magnitude over
CPython.
John Nagle

This is already done in RPython:

http://codespeak.net/pypy/dist/pypy/doc/coding-guide.html#restricted-python

I was at the PyCon It conference the other day and one of the
PyPy people claimed that RPython is up to 300X faster than Python.

Michele Simionato
 
A

Antoon Pardon

| > For him to imply that Python is anti-flexibility is wrong. Very
wrong..
| > He should look in a mirror. See below.
|
| My impression is that python supporters often enough show
| some anti-flexibility attitude.

More so than supporters of most other languages, in particular Scheme?

Well to my knowledge (which could be vastly improved), scheme doesn't
have some Zen-rules that include something like this.

I tried to google for similar remarks in relation to scheme but I
got no results. Maybe your google skills are better.
Here's the situation. Python is making inroads at MIT, Scheme home turf.
The co-developer of Scheme, while writing about some other subject, tosses
in an off-the-wall slam against Python. Someone asks what we here think.
I think that the comment is a crock and the slam better directed, for
instance, at Scheme itself. Hence 'he should look in a mirror'.

| Yes science is different. The difference is the following. Should
| science only know the Newtonian vectoral mechanics and someone
| would come up with the Lagrangian approach, nobody would protest
| against this new approach by remarking that there should only be
| one obvious approach,

The history of science is a history of innovation and resistance to
innovation. Do you have information that the introduction of the
Lagrangian approach was exceptional? Do you really think that no college
student has ever groused about having to learn another approach that is
only equivalent to what he already knows?

Yes the history of science is a history of innovation and resistance.
But the resistance to my knowledge has never used the argument that
there should (preferably) be only one obvious way to do things.

The student example is IMO not appropiate. There is a difference between
prefering not having to learn something yourself and argueing something
shouldn't be available in general.
| Yet these kind of remarks are made often enough when someone suggest a
| change to python.

So? Tim wrote 'There should be one-- and preferably only one --obvious way
to do it'. The primary clause is that there should at least one. The
secondary clause is that once there is a good and obvious way to do
something, we take a hard look before adding another. As it is, there are
already multiple ways to do many things. And there are probably at least
10 suggested innovations for everyone accepted.

Yes I know that. But that doesn't stop a lot of python supporters in this news
group to come with a variation that suggests once there is an obvious way to do
something in python, there really is no need any more to look at ways
that do it differently. And if my memory doesn't betray me, corrections
from others to such variations are a rather recent occurence.
 
N

Neil Cerutti

Well to my knowledge (which could be vastly improved), scheme
doesn't have some Zen-rules that include something like this.

I tried to google for similar remarks in relation to scheme but
I got no results. Maybe your google skills are better.

It's in _The Revised^%d Report on Scheme_, Introduction:

Programming languages should be designed not by piling feature
on top of feature, but by removing the weaknesses and
restrictions that make additional features appear necessary.

Of course, that was written well before Scheme had most of its
current features.
 
D

Diez B. Roggisch

John said:
When you have to start buying more servers for the server farm,
it's a real pain. I'm actually facing that because Python's HTML
parsing is so slow.

I can't believe that this is a general "python is to slow"-issue. After all,
lxml and cElementTree are _really_ fast - and written in C.

For example in TurboGears, there are two python-only templating systems -
KID & genshi (apart from others). The latter is a magnitude faster than the
former. After all, O(n^3) is O(n^3), regardless of the language...

And if only the html-parsing is slow, you might consider creating an
extension for that. Using e.g. Pyrex.

Diez
 
T

Terry Reedy

| > So? Tim wrote 'There should be one-- and preferably only one --obvious
way
| > to do it'. The primary clause is that there should at least one. The
| > secondary clause is that once there is a good and obvious way to do
| > something, we take a hard look before adding another. As it is, there
are
| > already multiple ways to do many things. And there are probably at
least
| > 10 suggested innovations for everyone accepted.
|
| Yes I know that. But that doesn't stop a lot of python supporters in this
news
| group to come with a variation that suggests once there is an obvious way
to do
| something in python, there really is no need any more to look at ways
| that do it differently.

Try suggesting on a Lisp or Scheme group that having only one type of
syntax (prefix expressions) lacks something and that they should add
variety in the form of statement syntax ;-) Hint: some Lispers have
bragged here about the simplicity of 'one way to do it' and put Python down
for its mixed syntax. (Of course, this does not mean that some dialects
have not sneaked in lists of statements thru a back door ;-).

Would you really want Python to have a hundred new features every release?

tjr
 

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top