I'm curious -- what is everyone's favorite trick from a non-python
language? And -- why isn't it in Python?
Here's my current candidate:
So the other day I was looking at the language Lua. In Lua, you make a
line a comment with two dashes:
-- hey, this is a comment.
And you can do block comments with --[[ and ---]].
--[[
hey
this
is
a
big
comment
--]]
This syntax lets you do a nifty trick, where you can add or subtract a
third dash to change whether or not code runs:
--This code won't run because it's in a comment block
--[[
print(10)
--]]
--This code will, because the first two dashes make the rest a comment,
breaking the block
---[[
print(10)
--]]
So you can change whether or not code is commented out just by adding a
dash. This is much nicer than in C or Python having to get rid of """ or
/* and */. Of course, the IDE can compensate. But it's still neat :)
python:
"""
print 10
"""
and
#"""
print 10
#"""
C++:
/*
print(10);
*/
and
///*
print(10);
//*/
?
Bye,
Enrico
[...]
>> --This code will, because the first two dashes make the rest a comment,
>> breaking the block
>> ---[[
>> print(10)
>> --]]
[...]
> python:
>
> """
> print 10
> """
>
> and
>
> #"""
> print 10
> #"""
>
> C++:
>
> /*
> print(10);
> */
>
> and
>
> ///*
> print(10);
> //*/
>
> ?
I think the *trick* here was that if you had larger blocks you'd only have
to change one side of the comment, i.e. the opening line, to de-comment the
block without searching the end of it and commenting that out aswell.
Ciao
Uwe
Duff's device is a classic masterpiece of lateral thinking.
It is not possible in Python for many fundamental reasons, we are not
at risk.
Lorenzo Gatti
>> /*
>> print(10);
>> */
>>
>> and
>>
>> ///*
>> print(10);
>> //*/
>>
>> ?
>
> I think the *trick* here was that if you had larger blocks you'd only
> have to change one side of the comment, i.e. the opening line, to
> de-comment the block without searching the end of it and commenting
> that out aswell.
Yes, but you can do that easily in C++ as well:
/*
print(10);
//*/
Change to:
//*
print(10);
//*/
I can't remember the exact pattern, but I remember using a
similar trick in BCPL where at least there was the excuse of not
otherwise having conditional compilation. C and C++ there is no excuse
for such tricks.
Google found Clive Feather's description of the BCPL trick at
http://www.lysator.liu.se/c/clive-on-history.html:
> I doubt it (though DMR may contradict me, of course). Every compiler
> I remember using allowed both // and /* */ type comment delimiters.
> Some also allowed | and \ to be used instead of /, so that || was also
> a comment-to-end-of-line, and \* ... *\ was an alternate block comment
> symbol. The latter was particularly useful, because it could be used
> to comment out blocks of code that included /* ... */ comments (as
> with C, comments do not nest). We used comments with vertical bars to
> implement a variety of conditional compilation:
>
> |**||| IF
> normal code
> |*|||| ELSE
> alternate code
> |*|||| CANCEL ELSE
> more normal code
> |*|||| ELSE
> more alternate code
> |**||| ENDIF
>
> By default, this would compile the "normal code". To switch to the
> "alternate code", the first line was changed to |**||* or |*||||
> instead. Because this comment symbol was used, the code could contain
> normal comments and the "commenting-out" reverse comments I described
> above.
Lowell
Off topic, but in C or C++ it's easier to do it using
#ifdef 1
...
#endif
Then you just have to change the 1 into 0 or vice versa. It also
prevents problems with nested comments.
Back on topic, the lack of such a construct in Python is actually one of
the very few things that bother me in the language. There are
work-arounds, of course; idle, for example, has a feature that prepends
a # to every line in the selection, or removes the # again. But not all
editors have such a feature, and even if they have it I still need to
select the block of code every time. Not that big a deal though.
--
If I have been able to see further, it was only because I stood
on the shoulders of giants. -- Isaac Newton
Roel Schroeven
I am very happy not to have such "tricks" in Python.
Any other (useful) suggestions?
Claudio
"Joseph Garvin" <k04...@kzoo.edu> schrieb im Newsbeitrag
news:mailman.837.11195961...@python.org...
>>And you can do block comments with --[[ and ---]].
>>
>>
>
>I am very happy not to have such "tricks" in Python.
>
>Any other (useful) suggestions?
>
>Claudio
>
>
I'm glad and all that not everyone shares my enthusiasm over Lua's
trick, and I'm glad that C/C++ can do it, but the original issue was
non-python language tricks in general. Lets keep the thread on track.
So far we've got lisp macros and a thousand response's to the lua trick.
Anyone else have any actual non-python language tricks they like?
Yeesh.
> As someone who learned C first, when I came to Python everytime I read
> about a new feature it was like, "Whoa! I can do that?!" Slicing, dir(),
> getattr/setattr, the % operator, all of this was very different from C.
>
> I'm curious -- what is everyone's favorite trick from a non-python
> language? And -- why isn't it in Python?
>
> Here's my current candidate:
[cut]
> This syntax lets you do a nifty trick, where you can add or subtract a
> third dash to change whether or not code runs:
I do it this way:
if 0: # Just for testing
print value
.....
You only need to change "if 0" to "if 1" and the code gets executed.
Thomas
--
Thomas Güttler, http://www.thomas-guettler.de/
> I'm curious -- what is everyone's favorite trick from a non-python
> language? And -- why isn't it in Python?
Long ago, I used to dabble in Forth. You could say, the entire Forth
language was a trick :-) It was interesting to be able to define your own
compiler commands, loop constructs and so forth.
One of the things I liked in Pascal was the "with" keyword. You could
write something like this:
with colour do begin
red := 0; blue := 255; green := 0;
end;
instead of:
colour.red := 0; colour.blue := 255; colour.green := 0;
Okay, so maybe it is more of a feature than a trick, but I miss it and it
would be nice to have in Python.
--
Steven
At least I am myself out of ideas, else I had
proposed a PEP already, to get it or have
provided a module for it.
So feel free to poke around with Python.
if(not \
"--[[" == "--[["):
# block of code
# --]]
as (already suggested) will also do the
trick with the block comment.
By the way, I personally find
--[[
good style comment block
]]--
or
[[--
good style comment block
--]]
much more intuitive than
--[[
bad style comment block
--]]
Claudio
"Joseph Garvin" <k04...@kzoo.edu> schrieb im Newsbeitrag
news:mailman.840.11196071...@python.org...
Why not:
from color import *
red := 0
blue := 255
green := 0
...
Because colour is not a module, it is a record. Sorry, I assumed that
people would be familiar with Pascal records (similar to C structs) and
it wouldn't need explanation. My bad :-(
The closest example in Python would be:
def class Colour:
def __init__(self, blue=0, green=0, red=0):
self.blue = blue
self.green = green
self.red = red
which would become something like:
def class Colour:
def __init__(self, blue=0, green=0, red=0):
# pseudo-Python code borrowing concept "with" from Pascal
with self:
blue = blue
green = green
red = red
And now you can see why Python doesn't support this idiom.
--
Steven.
You can try out new features yourself now using various python
extensions or descendants:
http://livelogix.net/logix/
- macros, no statement/expression distinction
http://students.ceid.upatras.gr/~sxanth/pyc/
- assignments are expressions, you can try other features never added
python like a ternary operator (x ? true action:false action)
http://boo.codehaus.org/
assignments are expressions, macros, static typing, no more "self"
required, ...
What do you think this actually does?
It doesn't do anything remotely resembling either of the things quoted
above. In fact, the "from color import *" line is pretty much useless here.
-Peter
> "Joseph Garvin" <k04...@kzoo.edu> ha scritto nel messaggio
> news:mailman.837.11195961...@python.org...
> > --This code won't run because it's in a comment block
> > --[[
> > print(10)
> > --]]
> >
> > --This code will, because the first two dashes make the rest a comment,
> > breaking the block
> > ---[[
> > print(10)
> > --]]
> >
> > So you can change whether or not code is commented out just by adding a
> > dash. This is much nicer than in C or Python having to get rid of """ or
> > /* and */. Of course, the IDE can compensate. But it's still neat :)
>
> python:
>
> """
> print 10
> """
>
> and
>
> #"""
> print 10
> #"""
It seems to me that this trick works in Python,too.
"""
print 10
#"""
and
#"""
print 10
#"""
You only have to change the first triple quote.
--
Doug Schwarz
dmschwarz&urgrad,rochester,edu
Make obvious changes to get real email address.
Maybe it would make more sense if it was done a la Visual Basic
with self:
.blue = blue
.green = green
.red = red
requiring a dot to be typed removes the ambiguity and gives the IDEs a
chance to Intellisense-ify your coding.
Some made a python recipe emulating this I believe. The python cookbook
search engine is down though so I cannot find the link.
At one point Guido van Rossum was advocating this use of "with" as well,
I believe:
http://mail.python.org/pipermail/python-dev/2004-March/043545.html
But I don't think it is being considered now. I think now "with" is
being proposed for something more like VB and C#'s "using" statement.
It automatically disposes of a resource when done with it:
http://wiki.python.org/moin/WithStatement
... that quickly becomes quite messy:
with A do begin
.....
with B do begin
.....
with C do begin
x := y;
end;
end;
end;
... and now you need to check the declarations of C, B, and A to
actually see what is assigned to what.
Worse yet, adding field 'x' to 'C' will (silently) break the code :(
I don't think it would be that nice to have it in Python.
--
Sergei.
> Claudio Grondi wrote:
>
> So far we've got lisp macros and a thousand response's to the lua trick.
> Anyone else have any actual non-python language tricks they like?
Higher-order functions like map, filter and reduce. As of Python 3000,
they're non-python tricks. Sigh - i guess it's time for me to get to know
list comprehensions a bit better.
The one thing i really do miss is method overloading by parameter type. I
used this all the time in java, and it really notice the lack of it
sometimes in python. No, it's not really possible in a typeless language,
and yes, there are implementations based on decorators, but frankly,
they're awful.
Yeah, and i'm with "if False:" for commenting out chunks of code.
tom
--
... but when you spin it it looks like a dancing foetus!
You do things like that in type-bondage languages like Java and C++
because you have to. Can you give an example of where you miss it in
Python?
If you want to do something different based on the type of an
argument, it's easy enough to do:
def foo (bar):
if type(bar) == whatever:
do stuff
else:
do other stuff
replace type() with isistance() if you prefer.
> No, it's not really possible in a typeless language,
Python is not typeless. It's just that the types are bound to the
objects, not to the containers that hold the objects.
Well it's coming to a future Python version, so apparently there are
many who can use it:
http://wiki.python.org/moin/Python3.0Suggestions#head-7df9d7035174644fdae024ed4a5ea0960a003ef5
I don't know if you'll have method overloading, but there will be type
checking. It's not actually compile-time "static typing" though. The
type checking still happens at run-time similar to your isinstance
example, making code run slightly slower than a normal python method:
"Type checking is going to slow down your code." -GVR 2005 keynote,
http://www.sauria.com/%7Etwl/conferences/pycon2005/20050324/The%20State%20of%20Python.html
> I'm curious -- what is everyone's favorite trick from a non-python
> language? And -- why isn't it in Python?
Although it's an optimization rather than language trick, I like the
inline functions/methods in C++. There has been a thread on that in the
past (http://tinyurl.com/8ljv5) and most consider it as useless and/or
very hard to implement in python without major changes in the language
(mainly because it would introduce 'compile-time' lookup of callables
instead of runtime, as it is now). Still it might be useful to have for
time-critical situations, assuming that other optimization solutions
(psyco, pyrex, weave) are not applicable.
George
{
for(int i = 0; i < 100; i++){
//do stuff
}
}
wrapping the for loop in { } makes the i a local variable and then you
can use it again in the code if not you will get a variable already
defined error.
As a side note python already keeps it a local variable, as most of us
know, and even if it did we can redifne it if we needed with ease.
Jeff
Jeffrey Maitland <jeff.m...@gmail.com> writes:
> [...]
>
> {
> for(int i = 0; i < 100; i++){
> //do stuff
> }
> }
>
> wrapping the for loop in { } makes the i a local variable
It's local anyway.
> and then you can use it again in the code if not you will get a
> variable already defined error.
Only in compilers created by this infamous company.
Tschö,
Torsten.
--
Torsten Bronger, aquisgrana, europa vetus
> Roy Smith wrote:
>> Tom Anderson <tw...@urchin.earth.li> wrote:
>>>The one thing i really do miss is method overloading by parameter
>>>type. I used this all the time in java
>> You do things like that in type-bondage languages like Java and C++
>> because you have to. Can you give an example of where you miss it in
>> Python?
>
> Well it's coming to a future Python version,
The 'it' under discussion is 'method overloading by parameter type'. While
a few people have requested it, I have seen no indication that 'it' is
coming. I do not see even a mention of it in either page you referenced.
> http://wiki.python.org/moin/Python3.0Suggestions#head-7df9d7035174644fdae024ed4a5ea0960a003ef5
> I don't know if you'll have method overloading, but there will be type
> checking.
Perhaps, though Guido has concerns about the issue.
> "Type checking is going to slow down your code." -GVR 2005 keynote,
> http://www.sauria.com/%7Etwl/conferences/pycon2005/20050324/The%20State%20of%20Python.html
You left out " NOTE: Nothing's settled yet!!!!!!!!!!!!!!!!" and "
Reminder and Disclaimer
Nothing's settled yet!!!!!
Terry J. Reedy
> sometimes in python. No, it's not really possible in a typeless language,
> and yes, there are implementations based on decorators, but frankly,
> they're awful.
Python has strongly typed objects. Only names are typeless.
Terry J. Reedy
Did you not see the very next sentence I wrote which exactly clarified
my point that I was referring to type checking and not method
overloading? Way to quote me out of context. Type checking IS coming
to python in all likelihood ->
>>I don't know if you'll have method overloading, but there will be type
>>checking.
>>"Type checking is going to slow down your code." -GVR 2005 keynote,
>>http://www.sauria.com/%7Etwl/conferences/pycon2005/20050324/The%20State%20of%20Python.html
>
>
> You left out " NOTE: Nothing's settled yet!!!!!!!!!!!!!!!!" and "
> Reminder and Disclaimer
> Nothing's settled yet!!!!!
I also left out the dozens of angry rants that people wrote after Guido
first proposed static typing, leading him to change the proposal to
runtime type checking, which by definition will slow down the code.
Static typing is almost certainly not going to come to Python, but the
typing annotations ("def method(x : int) -> bool") can be used by other
tools perhaps to do optimizations at compile time.
Again, you are splitting hairs. His point still stands that it is not
possible to do method overloading in python (unless you use decorator
hacks). It may be possible to add this feature when type declarations
and type checking are added to a future version of python.
Thanks for the link George, It was interesting.
I think some sort of inline or deferred local statement would be useful
also. It would serve as a limited lambda (after it's removed), eval
alternative, and as a inlined function in some situations as well I think.
Something like:
name = defer <expression>
then used as:
result = name()
The expression name() will never have arguments as it's meant to
reference it's variables as locals and probably will be replaced
directly with names's byte code contents at compile time.
Defer could be shortened to def I suppose, but I think defer would be
clearer. Anyway, it's only a wish list item for now.
Regards,
Ron
1.) Language support for ranges as in Ada/Pascal/Ruby
1..10 rather than range(1, 10)
2.) Contracts
3.) With
Did you mean 1..9 or 1...10 or both or neither?
Can this construct be used like this: (i+1)..n ? If not, what would you
use? What is the frequency of range literals in the average piece of code?
Steve
You are right. There is a difference.
1..10 == range(1, 10 + 1)
> Can this construct be used like this: (i+1)..n ? If not, what would you
> use?
Sure. In Ruby, you can do
i = 2
n = 5
for x in (i+1)..n do
print x
end
Can't in Ada/Pascal as far as I remember.
> What is the frequency of range literals in the average piece of code?
Well! I certainly have not done a study with code metrics. You probably
can find something online. That probably will be variable and might
depend on individual language affordances.
BTW, Ruby's times loop is another thing I find better readable for a
few cases.
4.times {
print "Something ..."
}
than
for x in range(4):
print "Something ..."
class color: # americanized
red = 0
blue = 255
green = 0
Less typing than pascal. Also avoids those stupid little colons.
--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095
> I'm curious -- what is everyone's favorite trick from a non-python
> language? And -- why isn't it in Python?
One thing that I miss every once in a while is "pre-processing". I'm
wondering if I'm the only one here, since nobody seems to have brought
that up. For example, after testing is done and I need to release some
bit of code in production, I would like create the .pyc/.pyo, like so:
# pycompile -DMAX_FOO=100 -D__version__=1.0 -D__release__=1.stable foo_module.py
where pycompile, is an home baked script that maybe uses compile/compileall.
I know, I can do the preprocessing myself in pycompile, but this would
be a nice to have.
Regards
Steve
On 6/24/05, Joseph Garvin <k04...@kzoo.edu> wrote:
> As someone who learned C first, when I came to Python everytime I read
> about a new feature it was like, "Whoa! I can do that?!" Slicing, dir(),
> getattr/setattr, the % operator, all of this was very different from C.
<...snip...>
> Again, you are splitting hairs. His point still stands that it is not
> possible to do method overloading in python (unless you use decorator
> hacks). It may be possible to add this feature when type declarations
> and type checking are added to a future version of python.
Decorators are actually a syntax hack remember. Everything you can do in a
decorator you could do with python before since they work via nested scopes.
It is easy to write wrapper methods and I use them for many purposes but not
for type checking.
Wrapper methods are very useful to take out common checking code. The checking
of conditions does not really belong in the caller (the caller could forget),
it does not really belong in the called function since that is not that
functions purpose but putting it in a wrapper and having it wrap the called
function sure gives a nice seperation and makes life simpler.
u-huu... I wasn't aware of that. It is really a consensus on this; that
removing map, filter, reduce is a good thing? It will render a whole lot
of my software unusable :(
Sure, I guess I can port most of it to list comprehensions, but
reduce/map are so much nicer.
--
Mandus - the only mandus around.
>>Higher-order functions like map, filter and reduce. As of Python 3000,
>>they're non-python tricks. Sigh - i guess it's time for me to get to know
>>list comprehensions a bit better.
>
> u-huu... I wasn't aware of that. It is really a consensus on this; that
> removing map, filter, reduce is a good thing? It will render a whole lot
> of my software unusable :(
Python 3000 (or Python 3.0) is the designated "we're going to break
backwards compatibility" release. Your code won't necessarily work even
if map, filter, and reduce are kept.
Guido's current plans, such as they are, with links to his reasoning can
be found here:
http://www.python.org/peps/pep-3000.html
http://wiki.python.org/moin/Python3.0
Of course, there's no timetable for when this change will take place.
map, filter, and reduce are safe for quite some time.
--
Robert Kern
rk...@ucsd.edu
"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
There are so many things wrong with preprocessing, at least if you're
thinking of the way C/C++ implements it (cpp). Cpp a number of things.
1) It does file inclusion. Pythons "import" serves that purpose and does a
better job of it.
2) It defines constants. A simple assignment in Python does that just fine
(and in C++, enums and const variables do it).
3) It does conditional compilation. Just use "if" in Python. You can even
enclose function definitions inside an "if" body.
4) It lets you do macro expansion. Just write a function in Python.
The big problem with cpp is that it essentially lets you define a whole new
language. The code that is compiled/executed isn't anything like the code
that you see on the screen. This can lead to debugging nightmares.
BTW, if you *really* want to, you can use cpp with Python. For example, I
just wrote the following little program. It's in a language I'll call
Prethon, for lack of a better name. It comes in two files:
-------------------------------
Roy-Smiths-Computer:play$ cat pp.h
#define foo(bar) mySillyFunction(bar, 0)
def mySillyFunction(x, y):
x / y
-------------------------------
and
-------------------------------
Roy-Smiths-Computer:play$ cat pp.pre
#include "pp.h"
foo(37)
-------------------------------
I can use cpp to turn this into a Python program by doing "cpp pp.pre >
pp.py". When I run that, I get a run-time exception and a stack trace:
Roy-Smiths-Computer:play$ python pp.py
Traceback (most recent call last):
File "pp.py", line 13, in ?
mySillyFunction(37, 0)
File "pp.py", line 10, in mySillyFunction
x / y
ZeroDivisionError: integer division or modulo by zero
This is really confusing. I'm looking at my source code and don't see any
calls to mySillyFunction(). In the trivial example I've given, it's
obvious that it's a #define in pp.h, but in a real-life example, there can
be hundreds or thousands of included files in a project, scattered about
all sorts of different directories you may not even know exist. Trying to
figure out what's going on becomes a nightmare.
I think you'll be able to use "from __past__ import map, filter,
reduce" or something like that :) They don't have to be built-in.
- kv
Couldnt there just be a "functional" module ?...
from functional import map, filter, reduce
> On Friday 24 June 2005 05:58 am, Steven D'Aprano wrote:
>> with colour do begin
>> red := 0; blue := 255; green := 0;
>> end;
>>
>> instead of:
>>
>> colour.red := 0; colour.blue := 255; colour.green := 0;
>>
>> Okay, so maybe it is more of a feature than a trick, but I miss it and it
>> would be nice to have in Python.
>
> class color: # americanized
> red = 0
> blue = 255
> green = 0
The problem is, you have made colour (returning to English spelling
instead of foreign) into a class. If you need two colour variables, you
have to duplicate the code for the class (perhaps only changing the
numeric constants. You can't even make instances from the class, because
they all share the same RGB values, which is pretty useless if they are
meant to represent different colours.
> Less typing than pascal.
You have missed the point. I'm not comparing Python vs Pascal for
creating records representing RBG values. I'm talking about a Pascal
feature that reduced typing by allowing you to use an implicit record.
Here is one possible way you might use such a feature as a Python idiom,
letting "with" specify an implicit object. Instead of doing this:
# read a class attribute
print myobject.__class__.myattribute
# set an instance attribute
myobject.widget.datapoints[myobject.collector] \
= myobject.dispatcher(myobject.widget.current_value)
you might do this:
with myobject:
# read a class attribute
print .__class__.myattribute
# set an instance attribute
.widget.datapoints[.collector] = .dispatcher(.widget.current_value)
> Also avoids those stupid little colons.
Using := and = for assignment and equality is precisely as stupid as using
= and == for assignment and equality. Perhaps less stupid: why do we use
== for equals, but not ++ for plus and -- for minus?
--
Steven.
> Interesting thread ...
>
> 1.) Language support for ranges as in Ada/Pascal/Ruby
> 1..10 rather than range(1, 10)
What advantages do Pascal-like for loops give over Python for loops?
The only two I can think of are trivial:
(1) the Pascal-like for loop is six characters shorter to type:
for i = 1 to 10: # 16 chars
for i in range(1, 10): # 22 chars
(2) for very large ranges, you don't have to hold the entire list of
integers in memory. But you can use xrange() instead of range(), which
also doesn't hold the entire list in memory.
> 2.) Contracts
Explain please.
> 3.) With
Explain please.
--
Steven.
James probably meant Eiffel's Design by Contract. My favourite Python
implementation is Terence Way's http://www.wayforward.net/pycontract/
;-)
- kv
More likely they will be moved to something like itertools than "__past__".
Or just define them yourself:
def map(f, seq):
return [f(x) for x in seq]
def filter(p, seq):
return [x for x in seq if p(x)]
def reduce(f, seq, zero):
r = zero
for x in seq: r = f(r, x)
return r
--
Steve.
> On 6/25/05, Mandus <man...@gmail.com> wrote:
>
>> It is really a consensus on this; that removing map, filter, reduce is
>> a good thing? It will render a whole lot of my software unusable :(
>
> I think you'll be able to use "from __past__ import map, filter,
> reduce" or something like that :)
from __grumpy_old_bastard_who_cant_keep_up__ import map
:)
tom
--
Why do we do it? - Exactly!
> Tom Anderson <tw...@urchin.earth.li> wrote:
>
>> The one thing i really do miss is method overloading by parameter type.
>> I used this all the time in java
>
> You do things like that in type-bondage languages
I love that expression. I think it started out as 'bondage and discipline
languages', which is even better. I'm going to start referring to python
as a 'sluttily typed' language.
> like Java and C++ because you have to. Can you give an example of where
> you miss it in Python?
No. I don't generally go around keeping a list of places where i miss
particular features or find particular warts irritating. Still, my
medium-term memory is not completely shot, so i assume i haven't missed it
much in the last couple of days!
> If you want to do something different based on the type of an argument,
> it's easy enough to do:
>
> def foo (bar):
> if type(bar) == whatever:
> do stuff
> else:
> do other stuff
>
> replace type() with isistance() if you prefer.
Yeah, i'm well aware that this is possible - what it's not is a clean
solution. If i was into writing boilerplate, i'd be using C. Also, this
gets really nasty if you want to overload on multiple variables.
Also, it actually falls down really badly in combination with duck typing
- you can't use isinstance to ask if an object looks like a file, for
example, only if it really is a file. Sure, you can do a bunch of hasattrs
to see if it's got the methods it should have, but that doesn't tell you
for certain it's a file, and it's a pain in the arse to write. In a typed
language, you'd just ask if it implemented the Channel (for example)
interface.
>> No, it's not really possible in a typeless language,
>
> Python is not typeless. It's just that the types are bound to the
> objects, not to the containers that hold the objects.
No. Types are properties of variables; the property that objects have is
called class. Python has classes but not types. I realise that many, even
most, people, especially those using typeless languages like python or
smalltalk, use the two terms interchangeably, but there's a real and
meaningful distinction between them. I may be the last person alive who
thinks it's an important distinction, but by god i will die thinking it.
So let's recognise that we have slightly different terminologies and not
argue about it!
FWIW, these don't exactly reproduce behaviour of current built-ins.
Filter, for instance, doesn't always return lists and map accepts more
than one seq... Just my $.02.
- kv
If they go to itertools, they can simply be:
def map(f, *iterables):
return list(imap(f,*iterables))
def filter(f, seq):
return list(ifilter(f,seq))
George
sure - that will be possible. But the main point (for me) is to avoid
the horrible slow for-loop in python (reduce...). By using the builtin reduce, I
move the for-loop into the c-code which performs better.
map and filter with list-comprehensions is probably ok - I use
list-comprehensions a lot, but somehow like the syntax of map/filter
better.
When it comes to lambdas, I am not so sure. I use them all the time, and
I will certainly miss them, and I have used lambdas in ways which at
least take som tinkering to translate to normal def's (or rather
closures). But I am not sure yet whether I have cases which are
impossible to translate (hey, nothing is impossible, some things just
take a bit more time).
Oh, and by the way, I use python to solve PDEs :)
But as someone else said, this will take some time. And I can always put
the c-function back in my self when that time comes.
Another important point, which it seems Guido does not fancy very much,
is that Python can be an ok functional style language for those who like
it. I very much enjoy the concept of using different programming styles
within the same language. It is mostly a convenience - I admit that -
but it makes me more productive. I'll be very sorry if we take that away
from python.
Maybe I am to late to change Guido on this - but if we are many, maybe
we can!
but lambda is grammar, so probably not so easy to import?
> By using the builtin reduce, I
> move the for-loop into the c-code which performs better.
No. There is no hope of ever writing fast code when you do not actually
measure its performance.
Peter
With PEP343 (I guess in Python 2.5), you will be able to do something like:
with renamed(colour) as c:
c.red = 0; c.blue = 255; c.green = 0
I think however it is bad. Better solutions to me would be:
colour.setRgb(0, 255, 0)
or
c = myVeryLongNameColour
c.red = 0; c.blue = 255; c.green = 0
Regards,
Nicolas
I do.
Sounds reasonable, but not always the case, especially when dealing with
numpy arrays. At least that what some of my test shows. But then I
should probably write c-functions that deals with the numeric arrays
anyway.
Besides, functions like 'operator.add' is also in c, maybe that helps.
But I admit it's not a perfect example.
Not if the function is from an extension module. For some applications,
this can be quite common.
Of course, in a Python 3000 world, nothing stops anyone from using their
own extension module implementing map, filter, and reduce if they really
want to. TSBOOOWTDI in the language/stdlib, but it shouldn't stop anyone
from using other ways to do it that aren't in the stdlib if the
tradeoffs are right for them.
> 25 Jun 2005 13:15:16 -0700 skrev Devan L:
>> But by using the builtin reduce, you need to specify a function, which
>> probably slows it down more than any speed-up from the loop in C.
>
> Sounds reasonable, but not always the case, especially when dealing with
> numpy arrays. At least that what some of my test shows. But then I
> should probably write c-functions that deals with the numeric arrays
> anyway.
>
> Besides, functions like 'operator.add' is also in c, maybe that helps.
Yes, the C-coded operator.mul() was the counterexample that John Lenton came
up with when I challenged the speed advantage of reduce() over the
equivalent for-loop.
> But I admit it's not a perfect example.
Python is more about readability than raw speed, and I prefer a for-loop
over reduce() in that respect, too. If you need the best possible
efficiency you would probably have to code the loop in C. Incidentally, for
add() this has already been done with the sum() builtin.
Peter
>On Fri, 24 Jun 2005 15:47:45 -0700, James Stroud wrote:
>
>> On Friday 24 June 2005 05:58 am, Steven D'Aprano wrote:
>>> with colour do begin
>>> red := 0; blue := 255; green := 0;
>>> end;
>>>
>>> instead of:
>>>
>>> colour.red := 0; colour.blue := 255; colour.green := 0;
>>>
>>> Okay, so maybe it is more of a feature than a trick, but I miss it and it
>>> would be nice to have in Python.
How do you like the following?
>>> color = type('',(),{})() # an instance that will accept attributes
>>> vars(color)
{}
The single line replacing
"""
with colour do begin
red := 0; blue := 255; green := 0;
end;
"""
follows:
>>> vars(color).update(red=0, blue=255, green=0)
which sets all the attributes:
>>> vars(color)
{'blue': 255, 'green': 0, 'red': 0}
>>> color.blue
255
>>> color.red
0
>>> color.green
0
Of course, I defined a class on the fly above, so I could have given it defaults
as class variables (using English spelling ;-) :
>>> colour = type('Colour',(),dict(red=0,blue=255,green=0))() # an instance with defaults
>>> vars(colour)
{}
Which don't show up in the instance dict, but do show up as attributes:
>>> colour.red
0
>>> colour.green
0
>>> colour.blue
255
Then we can update the instance dict that holds its attributes:
>>> vars(colour).update(red=111,green=222,blue=333)
And they show up, shadowing the class vars
>>> vars(colour)
{'blue': 333, 'green': 222, 'red': 111}
You can do one attribute this way:
>>> vars(colour).update(red='RED')
>>> vars(colour)
{'blue': 333, 'green': 222, 'red': 'RED'}
though this is obviously more concise:
>>> colour.green = 'GREEN'
>>> vars(colour)
{'blue': 333, 'green': 'GREEN', 'red': 'RED'}
>>>
The class vars are still there, even though we don't have a local name binding for the class:
>>> map(vars(type(colour)).__getitem__, 'red green blue'.split())
[0, 0, 255]
The instance is separate:
>>> vars(colour)
{'blue': 333, 'green': 'GREEN', 'red': 'RED'}
We can clear those attributes from the instance dict:
>>> vars(colour).clear()
>>> vars(colour)
{}
And then they don't shadow the class vars, so getting attributes make the class vars show again:
>>> [getattr(colour, c) for c in 'red green blue'.split()]
[0, 0, 255]
Or:
>>> map(colour.__getattribute__, 'red green blue'.split())
[0, 0, 255]
Actually, you could make that a few characters shorter using a temporary short name to make
a kind of with inside a list comprehension:
>>> [[c.red, c.green, c.blue] for c in [colour]][0]
[0, 0, 255]
Though list comprehensions leak bindings:
>>> c
<__main__.Colour object at 0x02F8FFCC>
Which generator expressions don't:
>>> del c
>>> list(([c.red, c.green, c.blue] for c in [colour]))[0]
[0, 0, 255]
>>> c
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'c' is not defined
Or we can get the pairs and build a dict:
>>> [(c,getattr(colour, c)) for c in 'red green blue'.split()]
[('red', 0), ('green', 0), ('blue', 255)]
>>> dict([(c,getattr(colour, c)) for c in 'red green blue'.split()])
{'blue': 255, 'green': 0, 'red': 0}
Of course, rgb is usually ordered, so why not
>>> colour = type('Colour',(),dict(rgb=(0,255,0)))() # an instance with default rgb
>>> vars(colour)
{}
>>> colour.rgb
(0, 255, 0)
>>> colour.rgb = 111,222,333
>>> vars(colour)
{'rgb': (111, 222, 333)}
>>> colour.rgb
(111, 222, 333)
>>> type(colour).rgb
(0, 255, 0)
def mywith(o=myobject):
# read a class attribute
print o.__class__.myattribute
# set an instance attribute
o.widget.datapoints[o.collector] = o.dispatcher(o.widget.current_value)
mywith()
Or if we had a lambda-replacing anonymous def permitting full suites:
(def(o=myobject):
# read a class attribute
print o.__class__.myattribute
# set an instance attribute
o.widget.datapoints[o.collector] = o.dispatcher(o.widget.current_value)
)()
Is a one-character prefix to the dot objectionable?
>> Also avoids those stupid little colons.
>
>Using := and = for assignment and equality is precisely as stupid as using
>= and == for assignment and equality. Perhaps less stupid: why do we use
>== for equals, but not ++ for plus and -- for minus?
>
I agree, but I think := would be nice in python for RE-binding an existing
binding, wherever it is seen from the local context. Thus you could
write
def foo(): x:=123
and
x = 456
def bar():
x = 789
foo() # finds and rebinds local x
print x
bar() # -> 123
print x # -> 456
foo() # finds and rebinds the global x
print x # -> 123
but
del x
foo() #-> NameError exception, can't find any x to rebind
hm, wandered a bit OT there, ;-/
Regards,
Bengt Richter
"from __future__ import something" can change the compile-time behaviour
of Python, so it is possible.
--
Steven.
In his State of Python 2005 address, Guido estimated 1/2 +1, 1/4 +/-0,
1/4 -1 on this. So majority of those with opinion, not 'consensus'. Then
there is his vote...
Terry J. Reedy
> Steven D'Aprano wrote:
>> One of the things I liked in Pascal was the "with" keyword. You could
>> write something like this:
>>
>> with colour do begin
>> red := 0; blue := 255; green := 0;
>> end;
>>
>> instead of:
>>
>> colour.red := 0; colour.blue := 255; colour.green := 0;
>>
>> Okay, so maybe it is more of a feature than a trick, but I miss it and it
>> would be nice to have in Python.
>>
>
> With PEP343 (I guess in Python 2.5), you will be able to do something like:
> with renamed(colour) as c:
> c.red = 0; c.blue = 255; c.green = 0
>
> I think however it is bad. Better solutions to me would be:
>
> colour.setRgb(0, 255, 0)
But that is no help, because the setRgb method will be implemented as
def setRgb(r, g, b):
self.red = r; self.green = g; self.blue = b
which is exactly the usage case for a with statement:
def setRgb(r, g, b):
with self:
.red = r; .green = g; .blue = b
> or
>
> c = myVeryLongNameColour
> c.red = 0; c.blue = 255; c.green = 0
Namespace pollution. It might not matter if c is a temporary variable
inside a function or method, but it does matter if your top-level code is
full of such constructs. Or for that matter, your interactive Python
session.
--
Steven.
Good grief! You've been spying on Mandus! How else could you possibly know
that he doesn't measure performance? Are you running a key-logger on his
machine? *wink*
For the record, perhaps now is a good time to mention that even Guido
recommended the use of map, filter and reduce in some circumstances:
"Try to use map(), filter() or reduce() to replace an explicit for loop,
but only if you can use a built-in function: map with a built-in function
beats for loop, but a for loop with in-line code beats map with a lambda
function!"
http://www.python.org/doc/essays/list2str.html
He specifically mentions that the reason map will often beat a for loop is
that it moves the work out of Python into the underlying C code.
That is also one of the reasons that ''.join(L) is faster than
s = ''
for item in L:
s = s + item
Do we really need to profile our code every single time to know this?
Isn't it reasonable to just say, "I use join because it is faster than
adding strings" without being abused for invalid optimization?
--
Steven.
On Saturday 25 June 2005 11:08 am, Steven D'Aprano wrote:
> The problem is, you have made colour (returning to English spelling
> instead of foreign) into a class. If you need two colour variables, you
> have to duplicate the code for the class (perhaps only changing the
> numeric constants. You can't even make instances from the class, because
> they all share the same RGB values, which is pretty useless if they are
> meant to represent different colours.
py> class color:
... pass
...
py> def with(classname, **kwargs):
... classname.__dict__.update(kwargs)
...
py> with(color, red=0,
... blue=255,
... green=255)
py>
py> color.blue
255
Is this what you want to do?
> > Also avoids those stupid little colons.
>
> Using := and = for assignment and equality is precisely as stupid as using
> = and == for assignment and equality. Perhaps less stupid: why do we use
> == for equals, but not ++ for plus and -- for minus?
The colons are to make it look more official or something. They are useless
and hence stupid. The two equals signs for comparison could be argued to be
redundant, but the colons are absolutely unecessary. I thought they were
pointless 18 years ago when I learned pascal in highschool and after 20
years, I still think they are still pointless.
--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095
> Of course, in a Python 3000 world, nothing stops anyone from using their
> own extension module implementing map, filter, and reduce if they really
> want to. TSBOOOWTDI in the language/stdlib, but it shouldn't stop anyone
> from using other ways to do it that aren't in the stdlib if the
> tradeoffs are right for them.
Now that's a good point. Since Guido has said that one of the major
motivations for removing the functional programming tools like map, filter
and reduce is that There Should Be Only One Obvious Way To Do It, and
Guido also seems to really like list comprehensions, is it fair to
assume that for-loops will be removed from Python 3000 too?
Or are they safe until Python 4000?
*wink*
Of course, I also know that Guido has said a foolish consistency
is the hobgoblin of little minds, and I would never accuse him of being a
little mind. But one of the things I like about Python is that it has
found a nice balance between There Is Always Another Way, and The Language
Is A Straight Jacket.
It is blindingly easy to refactor map and filter as in-line list comps,
and Guido's comments suggest to me that they are safe until list comps are
significantly faster. But reduce needs to be re-factored as a for loop,
with all the disadvantages that implies. I think that if people like
Mandus have good real-world usage cases for reduce, it can be saved, at
least as part of itertools.
--
Steven.
> Python is more about readability than raw speed, and I prefer a for-loop
> over reduce() in that respect, too.
Fascinating. I prefer reduce for readability. "Reduce this list to one
value, using this known behaviour" seems to work for me better than:
"Oh look, here is a new name being defined. What is it for I wonder? Now
it is being used in a for loop. Ah, the loop appears to be implementing
the well-known reduce behaviour from Lisp. I bet that means that the name
is a temporary placeholder just being used to hold the intermediate
results of from the for loop. Yes, that seems to be the case."
Funny how people differ in what they find readable :-)
--
Steven.
I think that fails "==".
> On Saturday 25 June 2005 11:08 am, Steven D'Aprano wrote:
>> The problem is, you have made colour (returning to English spelling
>> instead of foreign) into a class. If you need two colour variables, you
>> have to duplicate the code for the class (perhaps only changing the
>> numeric constants. You can't even make instances from the class, because
>> they all share the same RGB values, which is pretty useless if they are
>> meant to represent different colours.
>
> py> class color:
> ... pass
> ...
> py> def with(classname, **kwargs):
> ... classname.__dict__.update(kwargs)
> ...
> py> with(color, red=0,
> ... blue=255,
> ... green=255)
> py>
> py> color.blue
> 255
>
> Is this what you want to do?
No it isn't. That doesn't help at all if you want to do something
other than assigning to instance attributes.
For starters, it doesn't help me do this:
with colour:
print "Blue =", .blue
print "Green =", .green
print "Red =", .red
or anything more complex:
with my_directory_object:
L = .raw_paths
L.append("~/custom/")
# move the last directory looked to the front
# and the current directory to the end
.normalise(L, first=.last_dir, last=".")
.paths = L
try:
.currentpos += 1
except AttributeError:
.currentpos = 0
The point is that a hypothetical "with" block would have to allow
arbitrary access to dotted names: getting, setting, deletion, and method
calling, not just one very limited form of keyword assignment.
>> > Also avoids those stupid little colons.
>>
>> Using := and = for assignment and equality is precisely as stupid as using
>> = and == for assignment and equality. Perhaps less stupid: why do we use
>> == for equals, but not ++ for plus and -- for minus?
>
> The colons are to make it look more official or something.
That is the most ridiculous thing I have ever heard about a programming
language.
Has it escaped your notice that every language has to distinguish in
some way between "x equals 1" in the sense of assignment and "x equals 1"
in the sense of comparisons? "x = 1" is ambiguous.
A language might use constructs like:
"SET x = 1" and "x = 1"
for assignment and comparison, or do what Python does:
"x = 1" and "x == 1"
or do what Pascal does:
"x := 1" and "x = 1"
Even if the compiler can always unfailing tell them apart from context,
for the sake of the human programmers who have to read and write the code,
it is important to have two different operators.
> They are useless and hence stupid.
Useless huh? Just try leaving them out and see how useless they are.
> The two equals signs for comparison could be argued to be
> redundant,
No they aren't redundant, because assignment and equality testing are very
different. And in Python, you can even use them in the same place, so you
can't expect the compiler to tell them apart from context.
py> x = 2 # did I mean assignment or comparison?
> but the colons are absolutely unecessary. I thought they were
> pointless 18 years ago when I learned pascal in highschool and after 20
> years, I still think they are still pointless.
You didn't learn Pascal very well then if you can't see the difference
between assignment and equality testing.
--
Steven.
> On Sun, 26 Jun 2005 04:08:31 +1000, Steven D'Aprano <st...@REMOVETHIScyber.com.au> wrote:
>
>>On Fri, 24 Jun 2005 15:47:45 -0700, James Stroud wrote:
>>
>>> On Friday 24 June 2005 05:58 am, Steven D'Aprano wrote:
>>>> with colour do begin
>>>> red := 0; blue := 255; green := 0;
>>>> end;
>>>>
>>>> instead of:
>>>>
>>>> colour.red := 0; colour.blue := 255; colour.green := 0;
>>>>
>>>> Okay, so maybe it is more of a feature than a trick, but I miss it and it
>>>> would be nice to have in Python.
>
> How do you like the following?
> >>> color = type('',(),{})() # an instance that will accept attributes
> >>> vars(color)
> {}
>
> The single line replacing
> """
> with colour do begin
> red := 0; blue := 255; green := 0;
> end;
> """
> follows:
> >>> vars(color).update(red=0, blue=255, green=0)
The point is that a hypothetical "with" block would have to allow
arbitrary access to dotted names: getting, setting, deletion, and method
calling, not just one very limited form of keyword assignment.
I understand how to manipulate __dict__ as an more complicated (dare I say
obfuscated?) way of assigning to object attributes.
[snip]
> We can clear those attributes from the instance dict:
>>>> vars(colour).clear()
>>>> vars(colour)
> {}
Which has the unfortunate side effect of also destroying any other
instance attributes.
>>you might do this:
>>
>>with myobject:
>> # read a class attribute
>> print .__class__.myattribute
>> # set an instance attribute
>> .widget.datapoints[.collector] = .dispatcher(.widget.current_value)
>>
>
> def mywith(o=myobject):
> # read a class attribute
> print o.__class__.myattribute
> # set an instance attribute
> o.widget.datapoints[o.collector] = o.dispatcher(o.widget.current_value)
> mywith()
[snip]
> Is a one-character prefix to the dot objectionable?
That's a good workaround, subject to namespace pollution issues, and one
that I'm aware of. Although do you really want to be creating a unique
function definition every time you want to use the with idiom?
I'm not about to stop using Python because of the lack of Pascal-like
"with" blocks. It is a nice feature to have, but I'm aware that Guido
prefers explicit to implicit and "with" is extremely implicit.
--
Steven.
>>Using := and = for assignment and equality is precisely as stupid as using
>>= and == for assignment and equality. Perhaps less stupid: why do we use
>>== for equals, but not ++ for plus and -- for minus?
>>
> I agree, but I think := would be nice in python for RE-binding an existing
> binding, wherever it is seen from the local context. Thus you could
> write
>
> def foo(): x:=123
>
> and
> x = 456
> def bar():
> x = 789
> foo() # finds and rebinds local x
> print x
> bar() # -> 123
> print x # -> 456
> foo() # finds and rebinds the global x
> print x # -> 123
>
> but
> del x
> foo() #-> NameError exception, can't find any x to rebind
>
> hm, wandered a bit OT there, ;-/
Given how much the use of global variables are discouraged, is it a
good idea to allow even more inter-namespace interactions?
--
Steven.
> On Sat, 25 Jun 2005 21:30:26 +0200, Peter Otten wrote:
>
>> Mandus wrote:
>>
>>> By using the builtin reduce, I
>>> move the for-loop into the c-code which performs better.
>>
>> No. There is no hope of ever writing fast code when you do not actually
>> measure its performance.
>
> Good grief! You've been spying on Mandus! How else could you possibly know
> that he doesn't measure performance? Are you running a key-logger on his
> machine? *wink*
His mentioning reduce() as a performance panacea was a strong indication
even without looking over his shoulders. He filled in some conditions in a
later post, but "[U]sing reduce ... performs better [than a for-loop]" is
just wrong.
> For the record, perhaps now is a good time to mention that even Guido
> recommended the use of map, filter and reduce in some circumstances:
Personally I wouldn't rely on authority when I can measure without much
hassle. And the lesson I take from Guido's essay is rather how he got to
his conclusions than what his actual findings were. After all, Python may
have advanced a bit since he wrote the text.
> Do we really need to profile our code every single time to know this?
No. Only if we care about the performance of a particular piece. And if we
do we are sometimes in for a surprise.
> Isn't it reasonable to just say, "I use join because it is faster than
> adding strings" without being abused for invalid optimization?
OK, I am making a guess: "".join(strings) is more often faster than
naive string addition than reduce() wins over a for-loop.
I don't think my pointed comment qualifies as "abuse", by the way.
Peter
>>> from itertools import ifilter
>>> def filter(f, seq):
... return list(ifilter(f,seq))
>>> filter(str.isalpha, 'not quite!')
['n', 'o', 't', 'q', 'u', 'i', 't', 'e']
>>> __builtins__.filter(str.isalpha, 'not quite!')
'notquite'
- kv
Probably the most pointless Python wart, I would think. The =/==
distinction makes sense in C, but since Python doesn't allow assignments
in expressions, I don't think there is any situation in which the distinction
is needed. Python could easily figure out whether you meant assignment
or equality from the context, just like the programmer does.
BASIC did it that way, IIRC. It always seemed like C was seriously twisted
for letting you get away with assignment in expressions in the first place.
I don't think Python's use of "==" has *ever* helped me find a bug, it
just creates them. I really think "=" ought to be accepted as well, and
"==" deprecated.
But, hey, nobody asked me, I guess. And it doesn't kill me to type the
extra "=". ;-)
Cheers,
Terry
--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com
Terry Hancock <han...@anansispaceworks.com> writes:
> [...]
>
> BASIC did it that way, IIRC.
Right.
> [...]
>
> I don't think Python's use of "==" has *ever* helped me find a
> bug, it just creates them. I really think "=" ought to be
> accepted as well, and "==" deprecated.
However, then you must forbid a=b=1 for assigning to two variables
at the same time.
Tschö,
Torsten.
--
Torsten Bronger, aquisgrana, europa vetus
Why? It's already handled as an exception in the syntax.
In C, what you say makes sense, because "b=1" is an expression as
well as an assignment. But I don't think Python reads it that way -- it
just has code to recognize multiple assignment as a statement. I think
I remember reading that in the Language Reference or something.
> On Saturday 25 June 2005 01:08 pm, Steven D'Aprano wrote:
>
>>Using := and = for assignment and equality is precisely as stupid as using
>>= and == for assignment and equality. Perhaps less stupid: why do we use
>>== for equals, but not ++ for plus and -- for minus?
>
>
> Probably the most pointless Python wart, I would think. The =/==
> distinction makes sense in C, but since Python doesn't allow assignments
> in expressions, I don't think there is any situation in which the distinction
> is needed. Python could easily figure out whether you meant assignment
> or equality from the context, just like the programmer does.
There are situations where Python can't figure it out:
>>> a = 1
>>> b = 2
>>> f = a == b
>>> print a, b, f
1 2 False
>>> f = a = b
>>> print a, b, f
2 2 2
--
If I have been able to see further, it was only because I stood
on the shoulders of giants. -- Isaac Newton
Roel Schroeven
On the other hand, == is easier to type than := (two taps on the same key
vs two different keys, and at least on a US/English keyboard, no shift key
required). Not only that, but := is more likely to be turned into some
bizarre smiley face by brain-dead IM clients :-)
Oops ! I've used filter only with lists and didn't know that it
preserves the type for strings and tuples. Here's a (hopefully) correct
version:
def filter(f,seq):
it = ifilter(f,seq)
if isinstance(seq,basestring):
return ''.join(it)
elif isinstance(seq,tuple):
return tuple(it)
else:
return list(it)
By the way, the documentation of filter is unclear on what is the
return type if seq is a subclass of list, tuple, str, or unicode; is it
type(seq) or the base builtin type ? Let's see:
def subclassFactory(cls):
return type("Dummy_" + cls.__name__, (cls,),
{'__new__' : lambda self, seq: cls.__new__(self, seq)})
baseToSub = dict([(base,subclassFactory(base))
for base in list,tuple,str,unicode])
f = lambda x: x.lower()
for Base,Sub in baseToSub.iteritems():
assert type(__builtins__.filter(f, Sub('lowerUPPERCap'))) is Base
for Base,Sub in baseToSub.iteritems():
for cls in Base,Sub:
args = (f, cls('lowerUPPERCap'))
assert filter(*args) == __builtins__.filter(*args)
George
Hmm... I used to be quite the fan of Python, yet not long ago I met
Ruby and fell in love almost instantly. Some of the features I like the
most:
- statement modifiers:
< "return a if a.value == true"
< "database.query(q) unless database.connect == error
(etc)
- unless as "if not", since it gives nicer code to read
< unless false then print 1 # this prints 1 forever
- iterators, such as times (already mentioned)
- 'case'
< case var
< when 3 then do_sth
< when 4 then do_sth_else
< # etc...
< end
- everything returns a value, so you can do:
< foo = case foo2
< when 1 then yadda_yadda
< when 2 then blah_blah
< # etc
< end
And when foo2 == 2 then "blah_blah" gets executed and returned as the
'case' return value, thus assigning foo the value that results from
evaluating blah_blah
And some more, but those are the ones I like the best and python
doesn't have :-)
- greetings -
Nicolas
if a.value == True:
return a
if not database.connect == error:
database.query(q)
Trading two words for one word doesn't necessarily make the code
better.
< unless false then print 1 # this prints 1 forever
while not False:
print 1
"unless" seems to become "while not", as opposed to "if not". Should be
more consistent.
>On Sat, 25 Jun 2005 23:08:10 +0000, Bengt Richter wrote:
>
[...]
>>
>> The single line replacing
>> """
>> with colour do begin
>> red := 0; blue := 255; green := 0;
>> end;
>> """
>> follows:
>> >>> vars(color).update(red=0, blue=255, green=0)
>
>
>The point is that a hypothetical "with" block would have to allow
>arbitrary access to dotted names: getting, setting, deletion, and method
>calling, not just one very limited form of keyword assignment.
Point taken.
>
>I understand how to manipulate __dict__ as an more complicated (dare I say
>obfuscated?) way of assigning to object attributes.
>
Yes, it's a bit obfuscated.
>
>[snip]
>
>> We can clear those attributes from the instance dict:
>>>>> vars(colour).clear()
>>>>> vars(colour)
>> {}
>
>Which has the unfortunate side effect of also destroying any other
>instance attributes.
You wouldn't do something unfortunate, would you? ;-)
I just wanted to clear them all at that point in the interaction.
>
>
>>>you might do this:
>>>
>>>with myobject:
>>> # read a class attribute
>>> print .__class__.myattribute
>>> # set an instance attribute
>>> .widget.datapoints[.collector] = .dispatcher(.widget.current_value)
>>>
>>
>> def mywith(o=myobject):
>> # read a class attribute
>> print o.__class__.myattribute
>> # set an instance attribute
>> o.widget.datapoints[o.collector] = o.dispatcher(o.widget.current_value)
>> mywith()
>
>[snip]
>
>> Is a one-character prefix to the dot objectionable?
>
>That's a good workaround, subject to namespace pollution issues, and one
>that I'm aware of. Although do you really want to be creating a unique
>function definition every time you want to use the with idiom?
The only thing, ISTM, that would not also be unique in the with construct
is the function name, and you snipped the anonymnous def version that would
eliminate that. The main question in my mind would be binding of non-leading-dot
names. Would they work as in the suite of an "if" (i.e., binding in the same scope)
or as in a function with a new local scope that disappears on exit?
A function solves the alias name pollution problem, but prevents rebinding
anything external except explicitly declared globals, and closure cell vars
can't be rebound currently.
>
>I'm not about to stop using Python because of the lack of Pascal-like
>"with" blocks. It is a nice feature to have, but I'm aware that Guido
>prefers explicit to implicit and "with" is extremely implicit.
>
I wonder what happens when you have multiple withs, e.g.,
with obj_a:
.x = 1
with obj_b:
.x = 2
.y = 3
(I guess you would have to have a stack with only the latest with effective).
whereas a simple aliasing syntax like
(a=obj_a, b=obj_b):
a.x = 1
b.x = 2
b.y = 3
is unambigous and concise and the scope of the namescan be limited
to prevent name pollution at compile time.
OTOH, what should
(a=obj_a):
a = 123 # XXX ??
mean? Should it mean obj_a=123 and rebind in that scope,
like a macro substitution of names at compile time?
I guess the corresponding with thing would be
with obj_a:
. = 123
Regards,
Bengt Richter
>On Sat, 25 Jun 2005 23:08:10 +0000, Bengt Richter wrote:
>
>>>Using := and = for assignment and equality is precisely as stupid as using
>>>= and == for assignment and equality. Perhaps less stupid: why do we use
>>>== for equals, but not ++ for plus and -- for minus?
>>>
>> I agree, but I think := would be nice in python for RE-binding an existing
>> binding, wherever it is seen from the local context. Thus you could
>> write
>>
>> def foo(): x:=123
oops, for below example, needs global declaration
def foo():
global x
x:=123 #note that x:=123 searches outward through nested scopes,
#not including globals unless explicitly declared, whereas
# x=456 would always {re}bind the global x, as usual with a global x declared.
>>
>> and
>> x = 456
>> def bar():
>> x = 789
>> foo() # finds and rebinds local x
>> print x
>> bar() # -> 123
>> print x # -> 456
>> foo() # finds and rebinds the global x
oops, not so, unless foo has correction above
>> print x # -> 123
>>
>> but
>> del x
>> foo() #-> NameError exception, can't find any x to rebind
>>
>> hm, wandered a bit OT there, ;-/
>
>Given how much the use of global variables are discouraged, is it a
>good idea to allow even more inter-namespace interactions?
>
I forgot some of my previous thoughts on this. It's not as wild as it appears ;-)
I forgot to mention that of course a symbol found in __builtins__ by way
of the usual default lookup should not be rebound. And only globals explicitly
declared should be rebound (error in code above, since foo doesn't have global x).
So that limits it to the local scope and nested scopes and declared globals not
preempted by nearer nested scope variable names.
This is motivated by currently not being able to rebind a closure variable in
a nested scope, and the requirement of pre-existence within a limited range of
namespaces that can (I think ;-) be statically analyzed for is meant to prevent
new accidental collision problems.
Regards,
Bengt Richter
Okay, I see what you mean. I can't ever recall having needed the
second form, though.
Of course, you could still do assignment like this:
a, b = (1,)*2
But I guess that's not exactly elegant. ;-)
I use it all the time with Numeric's rich comparisons.
mask = some_arr == 999
> Of course, you could still do assignment like this:
>
> a, b = (1,)*2
>
> But I guess that's not exactly elegant. ;-)
Ya think? :-)
--
Robert Kern
rk...@ucsd.edu
"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
>> You need to differentiate
>> a = b = 1
>> from
>> a = b == 1
>
> Okay, I see what you mean. I can't ever recall having needed the
> second form, though.
>
> Of course, you could still do assignment like this:
>
> a, b = (1,)*2
>
> But I guess that's not exactly elegant. ;-)
In general that is not the same thing as a = b = obj.
py> a, b = ([], [])
py> a.append(1)
py> b
[]
py> a = b = []
py> a.append(1)
py> b
[1]
--
Steven.
What you wrote isn't, but what Terry wrote is.
In [1]: a, b = ([],)*2
In [2]: a.append(1)
In [3]: b
Out[3]: [1]
In [4]: a is b
Out[4]: True
That's what Python originally did, before release 0.9.6 (search
Misc/HISTORY for eqfix.py). Even this is ambigous then:
a = b
Especially at an interactive prompt, it's wholly ambiguous then
whether you want to change a's binding, or want to know whether a and
b compare equal.
Just yesterday, I wrote this in a script:
lastinline = ci == ncs - 1
This:
lastinline = ci = ncs - 1
means something very different (or means something identical,
depending on exactly how it is Python "could easily figure out" what I
intended <wink>).
Of course strange rules could have resolved this, like, say, "=" means
assignment, unless that would give a syntax error, and then "=" means
equality. Then
lastinline = ci = ncs - 1
would have been chained assignment, and something like
lastinline = (ci = ncs - 1)
would have been needed to get the intent of the current
lastinline = ci == ncs - 1
>Steven D'Aprano <st...@REMOVETHIScyber.com.au> writes:
>
>> On Fri, 24 Jun 2005 00:55:38 -0600, Joseph Garvin wrote:
>>
>> > I'm curious -- what is everyone's favorite trick from a non-python
>> > language? And -- why isn't it in Python?
>>
>> Long ago, I used to dabble in Forth. You could say, the entire Forth
>> language was a trick :-) It was interesting to be able to define your own
>> compiler commands, loop constructs and so forth.
>>
>> One of the things I liked in Pascal was the "with" keyword. You could
>> write something like this:
>>
>> with colour do begin
>> red := 0; blue := 255; green := 0;
>> end;
>>
>> instead of:
>>
>> colour.red := 0; colour.blue := 255; colour.green := 0;
>>
>> Okay, so maybe it is more of a feature than a trick, but I miss it and it
>> would be nice to have in Python.
>
>... that quickly becomes quite messy:
- When abused -
>with A do begin
> .....
> with B do begin
> .....
> with C do begin
> x := y;
> end;
> end;
>end;
Like many features that can be helpful when used well, and harmful when used
poorly, it's not a simple question whether it should be in any given language.
It also makes sense to consider whether other features already in the language
can fill the same need (though I don't know Python well enough to address that
yet). Even though I like "With" in VB and use it often, I always consider its
use a warning that perhaps that code should be factored into the class
somehow.
> if not database.connect == error:
> database.query(q)
Yeah, yeah, I know that :-)
What I mean is that most of the time I find the code more "readable" (I
know that more readable code ain't better code, but it helps when you
work with other people...).
> "unless" seems to become "while not", as opposed to "if not". Should be
> more consistent.
My mistake :-S
The comment in the code was erroneous, I shouldn't write messages to
the list while asleep ^_^
'unless' works as 'if not', not as 'while not'. Sorry for that :-)
Anyway, it does improve readability. I know that it doesn't necessarily
makes code better, but it's a nice "trick" that I like :-)
Other nice thing about ruby is declaring regexps as /regexp/ rather
than having to re.compile("regexp"), and having a built-in operator to
match against them (of course, as everything in ruby, overloadable in
each class :-))
-NIcolas
Since the user is the one bound with B&D languages, they are clearly
tops. Which makes Python a bottom.
<mike
--
Mike Meyer <m...@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Mike Meyer wrote:
>
> Since the user is the one bound with B&D languages, they are clearly
> tops. Which makes Python a bottom.
>
Well, we certainly hope Python has a safe word.
Metta,
Ivan
----------------------------------------------
Ivan Van Laningham
God N Locomotive Works
http://www.andi-holmes.com/
http://www.foretec.com/python/workshops/1998-11/proceedings.html
Army Signal Corps: Cu Chi, Class of '70
Author: Teach Yourself Python in 24 Hours
Ok - so sometimes reduce() for convenience (nha, that's just me...),
sometimes for performance. In some cases clever use of map/reduce/etc.
have given a good speedup - say 4 times that of for-loops. But going to
C can give 10 to 100 times speed up over that again... So it depends how
important the performance is. Going to C/Fortran is always a bit more
hassel, while reduce is something you can stick in your interactive
session to finish the work rather before than after lunch :)
[snip]
>
>> Isn't it reasonable to just say, "I use join because it is faster than
>> adding strings" without being abused for invalid optimization?
>
> OK, I am making a guess: "".join(strings) is more often faster than
> naive string addition than reduce() wins over a for-loop.
you're probably right.
> I don't think my pointed comment qualifies as "abuse", by the way.
neither think I.
--
Mandus - the only mandus around.
I use constraints programming at work, Check out "System Verilog" or
OZ/Mozart.
It would be great if this style of programming could be added to
Python.
It is a declarative programming style
(http://en.wikipedia.org/wiki/Declarative_programming), in which you
can state what discrete values constrained values can take , say in a
list. Give a set of functions that must be true for the variables then
sit back and generate one or many sets of variable values that fit the
constraints.
The OZ homepage has an example for solving the eight queens problem:
http://www.mozart-oz.org/documentation/fdt/node25.html#section.scripts.queens
My use would be for testing. In the electronic design automation
fields, there are several proprietary languages with this feature, here
is an example written in Cadence's Specman 'e' language:
http://www.asic-world.com/specman/specman_one_day2.html
Cheers, Paddy.
Buried in the generator test module (something like
lib/test/test_generators.py) are solutions for both 8Queens and Knight's
Tour. You might find these of interest.
Terry J. Reedy
- Pad.