I'm coming from Tcl-world ...

Heiko Wundram heikowu at ceosg.de
Sat Aug 3 02:17:25 CEST 2002


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.
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.





More information about the Python-list mailing list