1.) A 'for'-loop like in Tcl or in C, where you have separate
Init-, condition and increment-blocks, that control the loop.
(Of course, there's while, which can emulate all, but with that,
getting "continue" straight (that is: jump to the "increment-part"
of the body) is probably some hassle ...)
2.) A 'switch'-thing: like a big if-elif-elif-elif-...-else but which
evaluates its expression only once ... and then does all the comparisons.
3.) event-based scripting. (like 'fileevent','after',... in Tcl)
I've read somewhere, that with tkinter I get access to tcl's event-stuff,
But I was more after something that also works without Gui and without
actually using Tcl through Python. Is there a builtin module that
wraps the select() or poll() systemcall, and invokes the registered
functions if "their" respective channel becomes readable/writable
or a timer runs out ?
4.) "calls by reference": maybe I'm totally misunderstanding pythons
function-call-concepts. I want to pass a non-global variable to
a subroutine, have it changed there, and find that variable
changed in the calling context:
something like
def f( x ) : x=42
f(y); print y
of course doesn't work out the way I'm looking for. So what's the
easiest, and (if different) what's the python'iest way to do it ?
(apart from returning a tuple that contains the changed copy of the
object)
PS:
during playing around (stress-testing) I created a string object z
that contained 1 MB of zero-characters, then I did the following:
len(str(map(ord,z)))
with Python 1.5 I stopped it after an hour, when it still wasn't
finished, whereas in Python 2.2 (on a different, little slower, but
more recently installed) machine this took less than 10 seconds (iirc).
On a third machine (about double fast than the other two) with
Python 2.0 it also seems to take ages.
Is this a bug in old versions, or has something severely changed from
2.0 to 2.2 that affects performance so much ? Or is this just one of
many reasons to upgrade to 2.2.1 on all the machines ?-)
PPS: python'ing on linux I currently am.
--
Newsflash: Sproingy made it to the ground !
read more ... <http://avl.enemy.org/sproingy/>
The specific answer in this case is, use while, and
in fact the continue will do just what it should.
When in doubt, Python inclines to minimalism. A C-
like "for (;;)" isn't really necessary, and Python
doesn't go to the trouble of cluttering itself up
with this and other superfluities.
--
Cameron Laird <Cam...@Lairds.com>
Business: http://www.Phaseit.net
Personal: http://starbase.neosoft.com/~claird/home.html
The Python attitude, though, is that a LOT of
switches are bogus; they're better handled as
type resolution (switching between what amount
to different classes) or dictionary look-up.
Also, Pythoneers do much more multi-threading (at a scripting
level) than is typical for Tcl.
Welcome!
> I bought a small intro-book about python (it deals with 2.0 to 2.2 with
> some prospects to 3.0), which I've now almost read through, and now there
> are some goodies in Tcl, which I'm sure have their counterparts in Python,
> but I didn't find them so far. (This may also be due to the shortness of
> the book). These are:
>
> 1.) A 'for'-loop like in Tcl or in C, where you have separate
> Init-, condition and increment-blocks, that control the loop.
> (Of course, there's while, which can emulate all, but with that,
> getting "continue" straight (that is: jump to the "increment-part"
> of the body) is probably some hassle ...)
Someone else can probably help you better with this point. All I can say is
that I'm actually glad of the lack of a C-style 'for' loop in Python, as it
tends to be difficult to read and understand what it is doing unless you do
a lot of it.
For a better answer, try posting an example of the Tcl code that you'd like
to translate into Python, and a specific answer can be given which may bring
much enlightenment. There are a few of us around that know a little Tcl.
> 2.) A 'switch'-thing: like a big if-elif-elif-elif-...-else but which
> evaluates its expression only once ... and then does all the
comparisons.
I'm not sure what the proper idiom for this is, but I'd suspect that the
better Python users here have an awesome way of handling it, and that their
way makes one wonder why other languages ever bothered with a 'switch'- or
'select/case'-type statement.
> 3.) event-based scripting. (like 'fileevent','after',... in Tcl)
> I've read somewhere, that with tkinter I get access to tcl's
event-stuff,
> But I was more after something that also works without Gui and without
> actually using Tcl through Python. Is there a builtin module that
> wraps the select() or poll() systemcall, and invokes the registered
> functions if "their" respective channel becomes readable/writable
> or a timer runs out ?
Someone else will have to answer this one, too.
> 4.) "calls by reference": maybe I'm totally misunderstanding pythons
> function-call-concepts. I want to pass a non-global variable to
> a subroutine, have it changed there, and find that variable
> changed in the calling context:
> something like
> def f( x ) : x=42
> f(y); print y
> of course doesn't work out the way I'm looking for. So what's the
> easiest, and (if different) what's the python'iest way to do it ?
> (apart from returning a tuple that contains the changed copy of the
> object)
You can do this by putting the item to change in a list, dict, or instance
object rather easily (list case shown):
def incr(x):
x[0] += 1
x=[0]
print x[0]
incr(x)
print x[0]
This will output:
0
1
As always, keep in mind that it should be clear in some way exactly what the
side-effects of a call will be. Careful choice of names for
functions/methods will help greatly in this.
--
Daniel Fackrell (unle...@learn2think.org)
When we attempt the impossible, we can experience true growth.
I'm one of those weirdos that would use a dictionary for this. Here's
a very poor example:
#!/usr/bin/env python
import sys
def yes():
print 'yes'
return
def no():
print 'no'
return
options = {'-y': yes,
'-n': no,
}
for o in sys.argv[1:]:
try:
options[o]()
except:
print 'Unknown command line arguement'
> 1.) A 'for'-loop like in Tcl or in C, where you have separate
> Init-, condition and increment-blocks, that control the loop.
> (Of course, there's while, which can emulate all, but with that,
> getting "continue" straight (that is: jump to the "increment-part"
> of the body) is probably some hassle ...)
I think you'll find that you rarely need those, since you usually
iterate over some sequence. In those cases where you do need this
construct - yes, a while loop is the idiom you'll use.
> 2.) A 'switch'-thing: like a big if-elif-elif-elif-...-else but
> which evaluates its expression only once ... and then does all the
> comparisons.
PEP 275 proposes to include such a thing. You are encouraged to
comment on the PEP, either in this group, or by contacting the PEP
author:
http://www.python.org/peps/pep-0275.html
> 3.) event-based scripting. (like 'fileevent','after',... in Tcl)
> I've read somewhere, that with tkinter I get access to tcl's event-stuff,
> But I was more after something that also works without Gui and without
> actually using Tcl through Python. Is there a builtin module that
> wraps the select() or poll() systemcall, and invokes the registered
> functions if "their" respective channel becomes readable/writable
> or a timer runs out ?
I think the asyncore module is closest to that - although it is really
common to use select/poll explicitly, or to use threads.
>
> 4.) "calls by reference": maybe I'm totally misunderstanding pythons
> function-call-concepts. I want to pass a non-global variable to
> a subroutine, have it changed there, and find that variable
> changed in the calling context:
[...]
> of course doesn't work out the way I'm looking for. So what's the
> easiest, and (if different) what's the python'iest way to do it ?
The common approach is to mutate mutable objects. E.g.
class Counter:
pass
def count(o):
o.value += 1
p = Counter()
p.value = 0
count(p)
print p.value
Of course, for this application, you use proper methods:
class Counter:
def __init__(self):
self.value = 0
def count(self):
self.value += 1
p = Counter()
p.count()
> Is this a bug in old versions, or has something severely changed from
> 2.0 to 2.2 that affects performance so much ? Or is this just one of
> many reasons to upgrade to 2.2.1 on all the machines ?-)
I think this might be an improvement in the list.append
implementation: the map() call will add elements one-by-one, which
used to be quadratic, but isn't anymore.
Regards,
Martin
Python *does* have this ability, it just isn't called a "case" - it's
a *dictionary* lookup. Suppose you want to switch on the values 1, 2, and
3, and have them return, "red", "green", and "blue". Here is a case-like
approach implemented in Python:
def case1():
print "red"
def case2():
print "green"
def case3():
print "blue"
switch-table={}
switch-table[1]=case1
switch-table[2]=case2
switch-table[3]=case3
... do something to get the the value to switch on into, say, a variable called 'SwiTch'
# Here is your whole switch/case implementation as a one-liner
switch-table[SwiTch]()
Python's beauty is that you can use this sort of thing to "switch" on pretty much
*anything", not just an integer like in C, because the index into a dictionary can
be an integer, string, or pretty much *any* object.
My quick-n-dirty budgeting program (which is more a Python tutorial than
a really useful application) makes extensive use of this sort of thing
to implement a table-driven command interpreter. Here the "switch" is on
user input. If interested, have a look at:
http://www.tundraware.com/Software/hb/
--
------------------------------------------------------------------------------
Tim Daneliuk
tun...@tundraware.com
>>2.) A 'switch'-thing: like a big if-elif-elif-elif-...-else but
>>which evaluates its expression only once ... and then does all the
>>comparisons.
>
>
> PEP 275 proposes to include such a thing. You are encouraged to
> comment on the PEP, either in this group, or by contacting the PEP
> author:
>
> http://www.python.org/peps/pep-0275.html
>
This seems to me to just be syntactic sugar and thus unneeded. Switch/Case
like constructs are trivially, and more richly, implemented using
dictionaries to associate a switch value with a particular behavior or
result.
Unfortunately many of the given answers yet failed to make me happy :(
> 1.) A 'for'-loop like in Tcl or in C, where you have separate
> Init-, condition and increment-blocks, that control the loop.
> (Of course, there's while, which can emulate all, but with that,
> getting "continue" straight (that is: jump to the "increment-part"
> of the body) is probably some hassle ...)
[common answer: for(;;) is rubbish, use "while" or "for ... in" instead.]
Here, I think, I didn't make my concern clear enough:
in C/C++ (and similar in Tcl) I can do the following:
for (int i=0,string s="*" ; i<42 ; i++,s+=s) {
...
if (...) continue;
...
}
More and better examples of where a simple range/list/dictionary-
traversal just won't do it, surely exist.
Now, the transscription to while in C/C++ would be:
int i=0; string s="*";
while (i<42) {
...
if (...) goto increment;
...
increment:
i++; s+=s;
}
now, Python has no goto (rightly, so), thus by what shall I
replace the "continue", so I run through the incrementing part ?
How could python tell the increment-part from the rest of the body ?
the previous continue might be arbitrarily widely nested inside
some hierarchy of if's ...
> 2.) A 'switch'-thing: like a big if-elif-elif-elif-...-else but which
> evaluates its expression only once ... and then does all the comparisons.
[common answer: use dictionaries with functions as values ...]
coming from Tcl, dictionaries are not new to me, and even in Tcl,
I could start out like:
set switch(42) {puts 42}
set switch(666) {puts devil}
eval $switch($myvalue); # $myvalue being the switch-expression.
However, this has some impediments:
First: Only exact matches are possible with dictionaries, whereas
I'd have expected from a Python-switch to be able to specify a
comparison-function along, defaulting to exact match/identity.
Second: I want it all in the same scope; I want to set variables
in each "switch-branch" that are still valid outside,
and I don't want to clutter the namespace with a function for
each switch-branch. (yes, I know, I could reuse function-names after
placing the function-object into the dictionary, but...)
I'll have a look at the PEP-url given; thanks.
> 3.) event-based scripting. (like 'fileevent','after',... in Tcl)
[common answer: yes, there are modules: asyncore and select]
Thanks a lot, I'll have a look at them.
> 4.) "calls by reference":
> def f( x ) : x=42
[common answer: use mutable containers instead, e.g.: ]
[ def f(x): x[0]=42 ]
[ x= a list, containing my object as first (and perhaps only) element ]
[ f(x); then, x[0] outside of f is still 42 ]
It's not exactly what I fancied, but near enough :-)
> PS: [performance comparison among versions 1.5, 2.0 and 2.2 of python]
[answer: yes, there was a change in memory-allocation when appending
to lists]
That explains it :-)
Thus, whenever I intend to handle large data, I'd better upgrade
to a version at least 2.2 or so.
btw. the last attempt (on version 2.0) has taken 200 cpu-minutes so far
and still running on a 900MHz, with a job that took about 10 seconds
with 2.2 on a 300Mhz-machine. :-)
> Martin v. Löwis wrote:
>
> >>2.) A 'switch'-thing: like a big if-elif-elif-elif-...-else but
> >>which evaluates its expression only once ... and then does all the
> >>comparisons.
> >
> >
> > PEP 275 proposes to include such a thing. You are encouraged to
> > comment on the PEP, either in this group, or by contacting the PEP
> > author:
> >
> > http://www.python.org/peps/pep-0275.html
> >
>
> This seems to me to just be syntactic sugar and thus unneeded.
[snip]
Yeah, but being syntactic sugar doesn't necessarily make something a bad
idea. That's like saying you don't need for-loops since we have
while-loops. Heck, since we have operator.mul we don't need '*' anymore.
;-)
> The Python attitude, though, is that a LOT of
> switches are bogus; they're better handled as
> type resolution (switching between what amount
> to different classes) or dictionary look-up.
I confess, coming from a Smalltalk background, I had been using Python
for about eight months before I even wondered if it had a switch
construct or not
Jay O'Connor
http://www.r4h.org/r4hsoftware
On Fri, 2002-08-02 at 18:48, Andreas Leitgeb wrote:
> Here, I think, I didn't make my concern clear enough:
> in C/C++ (and similar in Tcl) I can do the following:
> for (int i=0,string s="*" ; i<42 ; i++,s+=s) {
> ...
> if (...) continue;
> ...
> }
There is no way to do anything like that in Python, there just isn't.
The only thing a for loop does is create an iterator on the object you
pass in after the "in" clause, and that iterator's next() method is
called until the iterator raises a StopIteration exception.
Why I'm telling you this is because there are (simple) ways to specify
functions that return iterators for your own types (classes are types in
Python).
The above code in Python would look something of the following:
for x in range(0,42):
s *= 2
<blah>
if <more blah>:
continue
<even more blah>
Doesn't look all the more complicated, does it? Just loop over one
variable, and specify all that extra stuff in the loop itself... :) You
can always rewrite any loop to loop over one variable only.
> now, Python has no goto (rightly, so), thus by what shall I
> replace the "continue", so I run through the incrementing part ?
Python has a continue statement, working just as you'd expect it to.
> First: Only exact matches are possible with dictionaries, whereas
> I'd have expected from a Python-switch to be able to specify a
> comparison-function along, defaulting to exact match/identity.
Of course, a switch statement only makes exact matches possible anyway.
Specifying the comparison function would only clobber the syntax (IMHO).
You can just as well do something of the following:
my_val = <switch expression>
if my_val == 1:
<blah>
elif 2 < my_val < 5:
<more blah>
elif my_val in range(6,25):
<some other blah>
else:
<default blah>
Looks almost like a switch statement, doesn't it?
> Second: I want it all in the same scope; I want to set variables
> in each "switch-branch" that are still valid outside,
> and I don't want to clutter the namespace with a function for
> each switch-branch. (yes, I know, I could reuse function-names after
> placing the function-object into the dictionary, but...)
Dictionaries aren't functions as they are in Tcl, but rather they are
builtin types. So you don't clobber any namespace when you try to look
up a dictonary key. You just write something like
my_switch_expr = 1
a = {1:"hello",2:"world"}
print a[my_switch_expr]
which would output hello in this case.
You'll only have a variable a running around which contains the
dictionary.
And by the way: Normally (at least at the moment) there are only two
namespaces in Python: Global and Local. Global means for the whole file
and local means local to the current function.
Global names are declared at module level, and local names at function
level. When you nest functions, these functions will share a common
namespace. (This doesn't mean that they will share namespace if you do a
recursive call or the like!)
If you need to access a global name from within a function, you'll have
to declare that name to be global directly after the function
declaration by saying "global <varname>".
Short example.
x = 3
def change_x_1():
x = 4
def change_x_2():
global x
x = 4
print x
change_x_1()
print x
change_x_2()
print x
will print:
3
3
4
as in the first function x isn't declared to be in the global namespace
(but rather assigned in the internal namespace), whereas in the second
case you explicitly state that when you refer to x you refer to the
global name called x.
> > 3.) event-based scripting. (like 'fileevent','after',... in Tcl)
> [common answer: yes, there are modules: asyncore and select]
> Thanks a lot, I'll have a look at them.
I'm sure those two modules answer all you need.
> [common answer: use mutable containers instead, e.g.: ]
> [ def f(x): x[0]=42 ]
> [ x= a list, containing my object as first (and perhaps only) element ]
> [ f(x); then, x[0] outside of f is still 42 ]
> It's not exactly what I fancied, but near enough :-)
This is based on the concept that Python always passes variables by
reference, and that there are some types that are simply not mutable
(such as tuples, integers, floats). This makes the language cleaner, as
you don't have all that mess you have in C/C++ where you have to watch
out about pointers, and the like.
I've never had any problems; what my functions simply always did was
return the values that needed to be changed in the calling function;
that way you don't have to mess about with putting a single argument in
a list just to be able to change it internal to the function...
Simple example:
x = 1
def inc(my_val):
return my_val+1, my_val+2
x,x_one_more = inc(x)
You can pass out more than one argument just by wrapping it in a tuple.
Well, hope this makes you look a little more favorable at Python than
what was suggested by your post. ;)
someone-put-me-on-python-advocacy-'ly yours,
and also
immitating-tim-peters-'ly yours, ;)
Heiko Wundram.
Clearly, minimalism can be taken to a ridiculous extreme. But, I still fail
to see what problem adding switch-case syntax fixes. It is certainly not
more compact than a dictionary approach AFAIKT, and it is (arguably) no clearer,
so why add more sugar here?
(Then again, I am fond of table (dictionary)-driven constructs because
they are, IMHO, much more maintainable and clear than the equivalent
in-line implementations... I'm a wee bit biased)
That is understandable, coming from another language and being used to
different idioms. But bear in mind that Python is not just a different
language... it's a different philosophy, and idioms that are common in other
languages may not be the Right Thing here.
[for loop]
> Here, I think, I didn't make my concern clear enough:
> in C/C++ (and similar in Tcl) I can do the following:
> for (int i=0,string s="*" ; i<42 ; i++,s+=s) {
> ...
> if (...) continue;
> ...
> }
This type of loop is very flexible; it's also hard to understand for someone
not familiar with this construction. I'm not unfamiliar with C and C++, but it
took me a while to figure out what exactly it was doing, and I'm still not sure
what happens at the continue.
> More and better examples of where a simple range/list/dictionary-
> traversal just won't do it, surely exist.
>
> Now, the transscription to while in C/C++ would be:
> int i=0; string s="*";
> while (i<42) {
> ...
> if (...) goto increment;
> ...
> increment:
> i++; s+=s;
> }
>
> now, Python has no goto (rightly, so), thus by what shall I
> replace the "continue", so I run through the incrementing part ?
Why not:
i, s = 0, "*"
while i < 42:
...
if not ...:
...
i += 1
s += s
[switch]
> However, this has some impediments:
> First: Only exact matches are possible with dictionaries, whereas
> I'd have expected from a Python-switch to be able to specify a
> comparison-function along, defaulting to exact match/identity.
> Second: I want it all in the same scope; I want to set variables
> in each "switch-branch" that are still valid outside,
> and I don't want to clutter the namespace with a function for
> each switch-branch. (yes, I know, I could reuse function-names after
> placing the function-object into the dictionary, but...)
The common if-elif-elif-... construct allows for all this flexibility. I know
you were looking for a different construct besides this, but as it is, Python
currently doesn't have one.
>>4.) "calls by reference":
>> def f( x ) : x=42
>
> [common answer: use mutable containers instead, e.g.: ]
> [ def f(x): x[0]=42 ]
> [ x= a list, containing my object as first (and perhaps only) element ]
> [ f(x); then, x[0] outside of f is still 42 ]
> It's not exactly what I fancied, but near enough :-)
Call by reference is something that is often used in other languages, but which
doesn't make all that much sense in Python. Such side effects are generally
frowned upon, because they make code less clear, among other things. Usually
there are better constructs. A function that returns the new value is one.
I don't know which book you used to learn Python, but it seems it taught you
the right things and common "Pythonic" idioms. It's only natural that you want
to find ways of doing it that are closer to what you're used to, but eventually
you may find yourself using the other constructs anyway, because they "feel
better". Just give them a try.
HTH,
--
Hans (base64.decodestring('d3VybXlAZWFydGhsaW5rLm5ldA=='))
# decode for email address ;-)
The Pythonic Quarter:: http://www.awaretek.com/nowak/
> Hi Andreas!
>
> On Fri, 2002-08-02 at 18:48, Andreas Leitgeb wrote:
>> Here, I think, I didn't make my concern clear enough:
>> in C/C++ (and similar in Tcl) I can do the following:
>> for (int i=0,string s="*" ; i<42 ; i++,s+=s) {
>> ...
>> if (...) continue;
>> ...
>> }
>
> There is no way to do anything like that in Python, there just isn't.
You should be able to do something like:
i = 0
s = "*"
while i < 42:
try:
...
if ...: continue
...
finally:
i += 1
s += s
But thats just really a direct translation, rather than looking for the
pythonic way of doing it.
--
Cameron Hutchison (cam...@xdna.net) | Onward To Mars
Huh? Maybe you mean there isn't this exact syntax which is correct.
But it's not hard to translate the above *idea* into:
def counted_doubler(iterations, s):
for i in xrange(iterations):
yield i,s # yields a tuple one by one to the for-loop
s+=s
for i,s in counted_doubler(42,'*'):
...
if ...:
continue
Actually python kind of leads you into finding good
explicit names for your ideas. Syntactic sugar is relatively
minimal compared to other languages.
So my basic point is: Don't translate syntax, translate ideas!
have fun,
holger
>> 3.) event-based scripting. (like 'fileevent','after',... in Tcl)
> [common answer: yes, there are modules: asyncore and select] Thanks a
> lot, I'll have a look at them.
YOu might also want to look at the asyncio module in the pyNMS package.
This works like asyncore, but uses SIGIO. It only works on Linux,
however. And it needs a little more work....
>
>> 4.) "calls by reference":
>> def f( x ) : x=42
> [common answer: use mutable containers instead, e.g.: ] [ def f(x):
> x[0]=42 ]
> [ x= a list, containing my object as first (and perhaps only) element
> ] [ f(x); then, x[0] outside of f is still 42 ] It's not exactly
> what I fancied, but near enough :-)
I usually use an idiom like the following:
def inc(x):
return x+1
x = 1
x = inc(x)
x = inc(x)
etc...
That is, the function just returns the new value, and you reassign the
name. although, for this simple example, that is unnecessary snd slower.
-- ^
\/ \/
(O O)
-- --------------------oOOo~(_)~oOOo----------------------------------------
Keith Dart
<mailto:kd...@kdart.com>
<http://www.kdart.com/>
----------------------------------------------------------------------------
Public key ID: B08B9D2C Public key: <http://www.kdart.com/~kdart/public.key>
============================================================================
> Martin v. Löwis wrote:
>
> > [PEP 275]
>
> This seems to me to just be syntactic sugar and thus unneeded.
> Switch/Case like constructs are trivially, and more richly,
> implemented using dictionaries to associate a switch value with a
> particular behavior or result.
Not really. Something like:
int a, b, c
switch (v) {
case 1:
a = 0
break;
case 1:
return b;
case 1:
c += 1
break;
}
would be tedious to do using dictionaries (i.e. where the different
cases need access to different bits of the local environment).
Cheers,
M.
--
On the other hand, the following areas are subject to boycott
in reaction to the rampant impurity of design or execution, as
determined after a period of study, in no particular order:
... http://www.naggum.no/profile.html
Frederic Bonnet has extended Tcl's asso-
ciative array to a new type called
"dictionary" which can more conveniently
be passed by reference. It's not widely
used (yet?).
.
.
Yes, you're right. The asyncore documentation could be better. Actually it's
very simple to use:
Write an object with the following methods:
writable() - return true if you wish to get write events
readable() - return true if you wish to get read events
handle_error() - called on any errors
handle_write_event() - called on write event
handle_read_event() - called on read event
also called on EOF, in that case reading will return ''
set socket_map[fd] to point to this object (multiple objects, more likely)
call asyncore.loop(optional_timeout)
The loop will return either on timeout or when one of the handlers
raises the asyncore.ExitNow exception.
That's all.
Everything else is just predefined objects you can inherit that help you
handle the little details. The asyncore.dispatcher handles setting up the
socket, listening for incoming connections, etc. The dispatcher_with_send
has a buffered send function, file_dispatcher handles pipes and other
non-socket fds, the asynchat module helps you implement two-way stateful
protocols.
If you have any ideas how to make it easier to use I'd love to hear them,
whether they're tcl-inspired or not...
Oren
No. The methods handle_read_event and handle_write_event are the low
level methods that get called directly by the asyncore loop. That's
what I use when I implement my own dispatcher from scratch. The dispatcher
class in the asyncore module implements them for you and calls the
handle_read and handle_write methods that you're supposed to override.
Oren
That kind of processing assumes that your language runtime owns a
mainloop. While this is a compromise that Tcl was willing to make, I
still think that must be left out of the programming language, and
should be part of libraries.
Regards,
Martin
> [common answer: for(;;) is rubbish, use "while" or "for ... in"
> instead.]
>
> Here, I think, I didn't make my concern clear enough:
> in C/C++ (and similar in Tcl) I can do the following:
> for (int i=0,string s="*" ; i<42 ; i++,s+=s) {
> ...
> if (...) continue;
> ...
> }
> More and better examples of where a simple range/list/dictionary-
> traversal just won't do it, surely exist.
As C-style goes this isn't a very pretty piece of code, especially
since you seem bent on building a string of 2**42 '*' characters. That
is a bit over the top, not to mention an exceedingly dull read. ;-)
Presumably you meant s += "*". That assumed, and also assuming you
don't modify i in the loop, here's the Python equivalent.
for i in range(42):
s = "*" * (i + 1)
...
if ...:
continue
...
BTW, using 'continue' is pretty rare, in my experience; 'break' is
_much_ more common.
>> 4.) "calls by reference": def f( x ) : x=42
> [common answer: use mutable containers instead, e.g.: ]
> [ def f(x): x[0]=42 ]
> [ x= a list, containing my object as first (and perhaps only)
> element ] [ f(x); then, x[0] outside of f is still 42 ]
> It's not exactly what I fancied, but near enough :-)
_Don't_ use a one element list: that's misleading to anyone (including
yourself) who reads that code later. If you don't wan't to use a full-
fledged class (including initializer function) just do:
class simple:
pass
If you really, _really_ need a mutable numeric type you could make one
yourself by imlementing a class which emulates a numeric type (see ch.
3.3.6 of the Python manual) but that shouldn't be necessary. More
importantly: please check _why_ you need a reference to an immutable
object. Usually you'll find that:
1 - That immutable object could/should be grouped with other ones to
form a proper class, or:
2 - The call-by-reference is needed because you need to have more than
one return value. Most languages have this limitation, but in Python
you can return as many values as you like, in a tuple. Then you'd get
something like:
def func(x):
...
x = 42
return (your_return_value, x)
x = 43
value, x = func(x)
- - -
The examples you give are typical ones if you try to emulate C-style in
Python. However, if you approach Python as Python you'll find nearly
all of those problems mysteriously and conveniently disappear. Well,
perhaps not that mysteriously: Python allows you to program at a much
higher level of abstraction than C, and with a lot fewer implementation
details worry about. Programming in Python is many times faster and a
lot less error prone than doing the same job in C, but if you approach
Python as C-with-a-strange-syntax you lose much of that advantage.
I'm not quite sure how Python compares to TCL as my experience with
that language is anything but extensive. The everything-is-a-string
paradigm is interesting and pretty unique, but also limiting. The
syntax seems to have been designed to help the interpreter rather than
the programmer, (IMHO, of course.) I suppose it will take a little
while for someone with that background to switch styles.
Robert Amesz
Agreed.
We already have polymorphic objects which provide a cleaner approach
to the vast majority of traditional switch statements. For the few
that remain, I find an indexed function table approach (generally
using dictionaries, sometimes lists) a far more elegant approach.
In the case of varying conditionals, an if/elif/else chain is hardly
less consise then a switch.
In other words, I don't perceive any advantage to be gained through
introducing a switch statement, except maybe to discourage the use of
cleaner approaches.
> (Then again, I am fond of table (dictionary)-driven constructs because
> they are, IMHO, much more maintainable and clear than the equivalent
> in-line implementations... I'm a wee bit biased)
Definately agreed.
Andrae Muys
Please, see also my second self-followup (which I'm going to post after
answering individual points)
> for x in range(0,42):
> s *= 2 [\n> ...]
This is not the same:
C(and Tcl)-for's increment-part is executed _after_ the body, and
_before_ evaluating the condition. _And_ it is the point where
'continue' jumps to)
Placing the increment-part after the end of the body will cause it
to be skipped by a 'continue' which I'd need to prevent.
Using Iterators prohibits me of altering the loop-variables inside
the body, which is no good style anyway ;-)
> Dictionaries aren't functions as they are in Tcl
Dictionaries aren't functions in Tcl, either. But Tcl uses
paranthesis to access the values from a dictionary, so for a
non-Tcl'er it may have looked like function-calls :-)
$dict(key) in Tcl --> dict['key'] in Python, and
$dict($keyvar) in Tcl --> dict[keyvar] in Python.
What I was referring to with "cluttering namespace with functions" was,
that others had suggested the following:
def handle_this(...): ...
def handle_that(...): ...
table['this']=handle_this; table['that']=handle_that; ...
# and then:
table[switchvar]()
which would have required a separate function for each branch,
which sometimes happens anyway (if the switch-branches would have
called the functions), but is not always the right thing.
> If you need to access a global name from within a function,
I wasn't speaking about global vars, but vars in the caller's
context. (accessing them is an important idiom in Tcl to
get a "call by reference"), but sometimes it seemed to be
quite useful even apart from that idiom.
[ mutating arguments passed to a function ]
> This is based on the concept that Python always passes variables by
> reference, and that there are some types that are simply not mutable
> (such as tuples, integers, floats). This makes the language cleaner, as
> you don't have all that mess you have in C/C++ where you have to watch
> out about pointers, and the like.
I've meanwhile recognized python's "call-by-reference"-mechanism
to be similar to java's (and completele unlike C/C++'s)
Assignment to parameter-vars inside a function get lost, but
mutations on arguments are visible outside.
There are some inconsistencies between the builtin types, whether
+=, etc. will replace or mutate the object on its left-hand-side.
> You can pass out more than one argument just by wrapping it in a tuple.
I know, but I'd like to have the choice, especially when dealing with
list-objects containing >million entries :-) (even though the referenced
objects are shared, the list itself would need to be copied)
> Well, hope this makes you look a little more favorable at Python than
> what was suggested by your post. ;)
Currently I'm in the phase of getting to know, what I can do and
what I need to do differently.
Once I think I've got some idea, I'll try to translate some of
my scripts to python and see, whether they become clearer or
obfuscated'er :)
Anyway, Python has some bonus' that make me even accept some other
shortcomings.
But the same still holds for Tcl, and lotsa other langs (even perl),
too ;-)
> someone-put-me-on-python-advocacy-'ly yours,
For tcl's switch, I can specify any of: exact-, glob- or regexp-match,
which is technically speaking, syntactic sugar for an if-elif*-else
construct, but really very good quality sugar, that I'm sorry to
miss here.
The quality of that sugar comes from not having to explicitely repeat
the comparison-function and common 'switchvar' argument.
Now that I write this, I suddenly see, how one can resemble a switch
almost cleanly with lambda-expressions and if-elif*-else:
switchvar=...
# "compare" could be regexp,glob,case-insensitive
case=lambda x: compare(x,switchvar)
if case('foo'):
...
elif case('foo*'):
...
you get the idea ...
I'm just curious about performance ...
> That is understandable, coming from another language and being used to
> different idioms.
Whenever I start to peek into a new language, I try to recognize
some abstract elements in it.
one of these "abstract elements" is described as such:
'A loop, whose body can directly and freely modify the
loop-var, thereby controlling the loop'
(one might for example want to step back one iteration eventually,
which seems unachievable with iterator-based loops)
('freely' means more than continue&break)
In C/C++/Java/perl/Tcl there is the for-loop that fulfills it.
Python lacks it.
Of course, one might question the usefulness of this feature,
but that's not in the scope of my original question.
Whether I really need it and whether and with what magic tricks I can
do without it, practise will show.
> Why not: [ replace continue with an if and make everything after
> the continue part of the if-block]
I wrote: the location of continue may be nested arbitrarily deep down
inside other if's.
> I don't know which book you used to learn Python, but it seems it taught you
> the right things and common "Pythonic" idioms.
It is the german translation of:
"Python Pocket Reference (2nd edition)" ("Python kurz&gut")
> you may find yourself using the other constructs anyway, because they "feel
> better". Just give them a try.
Yes, of course.
My intended question was not, how to program C/Tcl in python, but what
are Python's idioms for the mentioned "tasks".
The reason, this thread grew so fast, was that obviously I didn't
specify these "tasks" well enough.
Using generators can solve my problem in most cases, but it
still is not as general & powerful as the loop I asked for.
It's not that I ask for adding one to Python, it's just
that now I know, whenever I'd have felt like using such
a for-loop I'd have to do it differently.
> def counted_doubler(...): ... yield(i,s) ...
> for i,s in counted_doubler(42,'*'):
while this shows how to use more than one loop-var parallel,
(which looks like a useful idiom: thanks) it's not
a complete replacement for other languages' "for".
> Syntactic sugar is relatively
> minimal compared to other languages.
I don't understand, why "Syntactic sugar" has such a negative
connotation in most language-newsgroups.
It's usually syntactic sugar, that makes a language pleasing to
work with.
Languages without sugar (such as lisp/scheme but also various
assembler-langs as far as I know them) are really abhorrent for me.
Python also does have it's portion of s.s., and it's good it does.
While I mostly use linux myself, I'd feel more comfortable if my
python-scripts also ran on solaris and other unices at least.
> If you have any ideas how to make it easier to use I'd love to hear them,
> whether they're tcl-inspired or not...
yes, and I think it would be quite easy (up to details) to do
it in Python: (the following is python-like, but pseudo-code)
The implementations are missing, and could be based on asyncore.
module fileevents:
# register a channel for watching reads, writes or errors
# fd (a file-object or a numeric os-filedescriptor)
# cb (callback: a function object taking a few parameters
# defined later. Specifying Null here, will cancel
# a previously set up callback for that channel
# mode (what events to register for: readable,writable,error
# or more of them. If error is not registered for an fd
# at the time the internal select() returns one for the fd,
# then read- and/or write-callback will be called instead
# once and then the channel is automtically unregistered.)
# data (an arbitrary object, that will be passed to the
# callback as is)
def register(fd,cb,mode="read",data=None)
reg=register # alias :-)
# if a timer is set, the internally called select is called with
# an appropriate timeout, to awake at the first requested timer
# after the callback returns, select is automatically called again,
# with the time left until the next waiting timer.
def timer(seconds,cb,data=None,autoreset=0)
# unregister a channel:
unreg = lambda fd,mode,data=None: register(fd,None,mode,data)
# the main loop:
# calls select(), and when that finishes, calls all the
# registered callback-functions whose condition is met
# and/or all timer-callbacks. Exceptions thrown by callbacks
# are caught, and handled: (e.g. printed out, or some
# registered exception-handler called)
# If there is no timer and no registered fileevent left,
# or on some other condition (yet to be defined - perhaps a
# special exception, as in asyncore), loop() finishes.
def loop()
So much for the basic interface.
possible enhancements:
allow identifying & cancelling of timers
Some of the suggested features even go beyond Tcl's current
fileevents :-)
PS: this was a brainstorming, not yet a thought-out design.
If you - like quite some people do - program with lots of
different languages in the scope of - say - five years
you realize that syntactic sugar usually doesn't cut it.
You wan't to be able to express ideas and give good names
to them so that you later can maintain it. For me, python
helps a lot here.
> It's usually syntactic sugar, that makes a language pleasing to
> work with.
up to a certain degree, yes. E.g. perl certainly goes too far for me.
I professionally worked with perl for two years, day in and out.
That's just two years ago and i can't remember even basic stuff
due to the high ratio of !`{$[%&/ characters in a line (called
line-noise). IIRC, TCL was better for me in this area.
cheers,
holger
IIRC, it has been updated recently at
http://www.python.org/dev/doc/devel/lib/module-asyncore.html
The other comments about that example have appeared similarly in
other posts, and answered in their followups.
>>> 4.) "calls by reference": def f( x ) : x=42
> _Don't_ use a one element list: that's misleading to anyone (including
> yourself) who reads that code later.
since Python seems to keep all types as "first class objects", I thought
it would not matter whether I chose an integer or any other object for
the example.
Meanwhile I've recognized Python's "call-by-ref" to be similar to
Java's (probably because object-handling is similar between these
languages) and I can live with that.
Generally:
It depends on the context on whether it is better to
make use of call-by-ref or return a result.
If the object is a list of millions of entries, it is definitely
better to have a way of modifying the list in-place than returning
even a shallow copy of it.
> The examples you give are typical ones if you try to emulate C-style in
> Python.
I see this differently:
If you had to switch from Python to C (and you didn't know C yet),
you would most likely ask, how to create a dictionary, and how
to do lists of mixed typed objects.
Maybe you'd hack together a simple dictionary in C, so you could
continue to use this powerful tool.
I wouldn't call this "emulating Python-style" then.
> I'm not quite sure how Python compares to TCL as my experience with
> that language is anything but extensive.
What really counts for me is, what useful gadgets and idioms a language
provides me, to let me express the algorithms as concisely as
possible. Some simple things become quite complicated when
writing it in Tcl, others, easy in Tcl, seem to become difficult
in Python ...
perl, e.g. offers me a genious regexp-engine and -syntax (not only the
re-syntax itself, but also how it is embedded in perl: if (/bla.*/) ... ).
If I write something that uses lots of regexps, I use perl (which I
otherwise don't like that much)
Tcl offers me a powerful event-loop, direct access to any stackframe
up to global context, lets me view the bodies of previously defined
procedures, but unfortunately also has some over-sophisticated
builtins (e.g. exec) that are hard to work around, and some level of
obfuscation is needed to pass a list as separate args to a function.
Python offers me flexible function-handling (passing a dictionary as
arguments), lambda's, generators(yield), ... (and more to be discovered
by me), but lacks a general for-loop (as in C and others), lacks
an internal event-loop, and other things I've not yet come across.
[Roberts "IMHO"'s :) ]
> The everything-is-a-string paradigm is interesting and pretty unique,
> but also limiting.
Unique, yes, interesting: not all that much, limiting: nope.
> The syntax seems to have been designed to help the interpreter
> rather than the programmer,
Initially perhaps, but Tcl has developed far enough, so I don't
necessarily notice it from programmer's point of view.
I'm quite new to programming in Python and this puzzled me. Could you give
me an example of using dictionaries instead of switch?
Thank you very much!
-----------------------------------
Andres Rosado
Email: and...@despammed.com
ICQ: 66750646
Homepage: http://andres980.tripod.com/
"There is no choice before us. Either we must Succeed in providing
the rational coordination of impulses and guts, or for centuries
civilization will sink into a mere welter of minor excitements.
We must provide a Great Age or see the collapse of the upward
striving of the human race"
-- Alfred North Whitehead