From da@ski.org  Sat Mar  6 04:57:48 1999
From: da@ski.org (David Ascher)
Date: Fri, 5 Mar 1999 20:57:48 -0800 (Pacific Standard Time)
Subject: [Tutor] test - ignore
Message-ID: <Pine.WNT.4.05.9903052057340.176-100000@david.ski.org>

please ignore this test.




From da@ski.org  Mon Mar  8 04:36:39 1999
From: da@ski.org (David Ascher)
Date: Sun, 7 Mar 1999 20:36:39 -0800 (Pacific Standard Time)
Subject: [Tutor] Welcome
Message-ID: <Pine.WNT.4.05.9903072025530.154-100000@david.ski.org>

Welcome all --

I'm pleased -- the list has been created about two days ago, and it has
over two dozen subscribers.  I know many of the email addresses of the
subscribers, which means that there are at least a few 'old-timers'
around, and there are also others which are new to me, which is great --
hopefully some of you are novices who will feel free to ask questions, for
the others to answer.

Let me start by introducing myself -- my name is David Ascher, and I've
been programming in Python for about four or five years.  While I've just
co-authored a book called "Learning Python" with Mark Lutz, it's not a
book which was designed to teach programming.  I've been programming for
more than half my life, and I haven't taught programming in ages, so I
feel I'm a bit out of touch with what students new to programming need to
know, and what parts are hard to learn or unintuitive. I'm hoping that
with a little interaction between the students and the teachers on this
list, two goals can be reached -- 1) the folks who are trying to learn
programming with Python get the help they need, and 2) the folks who want
to develop better documentation for learning programming with Python get a
test audience to help them work out the pedagogics.

Well, I'll clear the stage and let the questions roll in.  

Cheers,

--david




From siegel@eico.com  Mon Mar  8 14:57:15 1999
From: siegel@eico.com (Arthur Siege;l)
Date: Mon, 08 Mar 1999 09:57:15 -0500
Subject: [Tutor] Children of all ages
Message-ID: <36D1D44300000A38@mail.eico.com> (added by mail.eico.com)

>Welcome all -- David is about half my age and has been prgramming probably
five times as long as I have. I have learned most of what I know about
programming with Python, and DA's PyOpenGL over the past few years. Somehow
I think graphics programming is a great place to start - particularly for
kid's. The fact that objects appear as objects - on the screen - helps to
make the process a bit less abstract. The beauty of Python, as a scripting
language and in interactive mode, is that it allows one to futz around -
great for learning. While I can now claim to grasp the basics of OOP and
have a handle around Python as a tool for further exploration, there as
still some basics I haven't gotten to. But what I want to explore is less
Python or any specfic syntax, but broader areas of technological ignorance.
Python is the tool that will allow me to explore. What I am not sure of is
the appropriateness of this approach to the founding concept of this list.
For example - sockets. I haven't a clue. Other than knowing that it is a
basic technology of the web. If it is an appropriate question here, how
might I use Python to get a grasp of the area??





From ajs@ix.netcom.com  Mon Mar  8 14:47:06 1999
From: ajs@ix.netcom.com (Art Siegel)
Date: Mon, 8 Mar 1999 09:47:06 -0500
Subject: [Tutor] Children of all ages
Message-ID: <002001be6974$803f2fa0$2e82f3d0@seigel.eico.com>

>Welcome all --


David is about half my age and has been prgramming probably five times as
long as I have.

I have learned most of what I know about programming with Python, and DA's
PyOpenGL over the past few years.

Somehow I think graphics programming is a great place to start -
particularly for kid's.  The fact that objects appear as  objects - on the
screen - helps to make the process a bit less abstract.


The beauty of Python, as a scripting language and in interactive mode, is
that it allows one to futz around - great for learning.

While I can now claim to grasp the basics of OOP and have a handle around
Python as a tool for further exploration, there as still some basics I
haven't gotten to.  But what I want to explore is less Python specific
syntax, but broader areas of technological ignorance.  Python is the tool
that will allow me to explore.

What I am not sure of is the appropriateness of this approach to the
founding concept of this list.

For example - sockets.  I haven't a clue. Other than knowing that it is a
basic technology of the web.

If it is an appropriate question here, how might I use Python to get a grasp
of the subject??



From geek+@cmu.edu  Mon Mar  8 16:47:00 1999
From: geek+@cmu.edu (geek+@cmu.edu)
Date: 8 Mar 1999 11:47:00 -0500
Subject: [Tutor] Children of all ages
In-Reply-To: <36D1D44300000A38@mail.eico.com> (added by mail.eico.com)
Message-ID: <emacs-smtp-22924-14051-65284-122680@export.andrew.cmu.edu>

--pgp-sign-Multipart_Mon_Mar__8_11:46:58_1999-1
Content-Type: text/plain; charset=US-ASCII

Then <siegel@eico.com> spoke up and said:
> still some basics I haven't gotten to. But what I want to explore is less
> Python or any specfic syntax, but broader areas of technological ignorance.
> Python is the tool that will allow me to explore. What I am not sure of is
> the appropriateness of this approach to the founding concept of this list.
> For example - sockets. I haven't a clue. Other than knowing that it is a
> basic technology of the web. If it is an appropriate question here, how
> might I use Python to get a grasp of the area??

This seems like as good a place as any.  For what little socket work
I've done, I've found the socket demos in the source distribution an
excellent place to start.  Unfortunately, this doesn't really teach
the theory behind it all, or give you a good grasp of how it works.
On the other hand, you do end up with tools that show you how to get a
basic socket server up and running.  The next big hurdle after that is
terminal handling (if you need it).

-- 
=====================================================================
| JAVA must have been developed in the wilds of West Virginia.      |
| After all, why else would it support only single inheritance??    |
=====================================================================
| Finger geek@andrew.cmu.edu for my public key.                     |
=====================================================================

--pgp-sign-Multipart_Mon_Mar__8_11:46:58_1999-1
Content-Type: application/pgp-signature
Content-Transfer-Encoding: 7bit

-----BEGIN PGP MESSAGE-----
Version: 2.6.2
Comment: Processed by Mailcrypt 3.3, an Emacs/PGP interface

iQBVAwUBNuP/A4dzVnzma+gdAQE0AAIAmGRSjJs1jQydb+jRi8VxrZSKmQxvmvJf
0MW9D5OL1pekdmHvlMFj+1te1agv6T8//iegwrhJ6wfpTg13duk8Jg==
=Q3/z
-----END PGP MESSAGE-----

--pgp-sign-Multipart_Mon_Mar__8_11:46:58_1999-1--



From alan.gauld@gssec.bt.co.uk  Mon Mar  8 17:39:47 1999
From: alan.gauld@gssec.bt.co.uk (Alan Gauld)
Date: Mon, 8 Mar 1999 17:39:47 -0000
Subject: [Tutor] RE: Tutor digest, Vol 1 #2 - 4 msgs
In-Reply-To: <199903081704.MAA00472@python.org>
Message-ID: <001e01be698a$a960a880$0acb9284@dumyat.gssec.bt.co.uk>

Since folks seem to be introducing themselves...

I am just starting with Python - looking for an alternative 
to Perl which I just hate for all sorts of reasons! Basically 
it offends my sense of programming purity. :-) But up to now 
it has been the only thing with that kind of sheer power...

I've been programming for about 15 years in C, C++, awk, 
Smalltalk, Lisp and Delphi.(Oh and COBOL but I try to forget 
that...)


Anyway, My point for a Python tutorial:

Explain the colon!!! It gets a passing mention in Lutz's book, 
none at all in Watter's book. It took me (as an experienced 
programmer) at least half an hour to figure out how/when 
the colon should be used(mainly by browsing the demo code) 
a beginner to programming with no concept of a 'block of 
code' will be baffled IMHO.

See ya'll around :-)

Alan G.



From M.Faassen@vet.uu.nl  Mon Mar  8 20:07:25 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Mon, 08 Mar 1999 21:07:25 +0100
Subject: [Tutor] RE: Tutor digest, Vol 1 #2 - 4 msgs
References: <001e01be698a$a960a880$0acb9284@dumyat.gssec.bt.co.uk>
Message-ID: <36E42DFD.A3BC9443@pop.vet.uu.nl>

Alan Gauld wrote:
> 
> Since folks seem to be introducing themselves...
> 
> I am just starting with Python - looking for an alternative
> to Perl which I just hate for all sorts of reasons! Basically
> it offends my sense of programming purity. :-) But up to now
> it has been the only thing with that kind of sheer power...
> 
> I've been programming for about 15 years in C, C++, awk,
> Smalltalk, Lisp and Delphi.(Oh and COBOL but I try to forget
> that...)
> 
> Anyway, My point for a Python tutorial:
> 
> Explain the colon!!! It gets a passing mention in Lutz's book,
> none at all in Watter's book. It took me (as an experienced
> programmer) at least half an hour to figure out how/when
> the colon should be used(mainly by browsing the demo code)
> a beginner to programming with no concept of a 'block of
> code' will be baffled IMHO.

This hangs together with 'indentation', though. Are you sure indentation
isn't explained in these books (I haven't read either). I don't recall
having had any problem grasping what the ':' was about (along with
indentation marking block structure). Of course I was already
experienced with other programming languages, so I don't count at as an
absolute beginner.

I agree a beginner tutorial should have a good explanation of 'block
structure' in programming, though. In Python this is marked by the : and
an indented block, but saying 'explain the colon' mystifies me. :)

Regards,

Martijn


From da@ski.org  Mon Mar  8 21:27:25 1999
From: da@ski.org (David Ascher)
Date: Mon, 8 Mar 1999 13:27:25 -0800 (Pacific Standard Time)
Subject: [Tutor] RE: Tutor digest, Vol 1 #2 - 4 msgs
In-Reply-To: <36E42DFD.A3BC9443@pop.vet.uu.nl>
Message-ID: <Pine.WNT.4.04.9903081257470.254-100000@rigoletto.ski.org>

On Mon, 8 Mar 1999, Martijn Faassen wrote:
> Alan Gauld wrote:
> > Explain the colon!!! 
>
> I agree a beginner tutorial should have a good explanation of 'block
> structure' in programming, though. In Python this is marked by the : and
> an indented block, but saying 'explain the colon' mystifies me. :)

Let me try to emphasize that I'd much rather see explanations than
defensive reactions.  If the questions are there, they indicate a need
which isn't met.  

Here's a first pass:

Python uses a combination of colons (:) and indented blocks to indicate to
the compiler what lines of code are to be grouped together in flow-control
statements like if, for, while, and other structural groupings like
function definitions (def) and class definitions (class).  In all of these
cases, the syntax is very much like when presenting an outline:

   This is the first section of the outline -- it has two subsections:
  
       This is the first subsection.

       This is the second subsection of the first section.
   
   This is the second section.

As you read this, the combination of consistent indentation and the : at
the end of the preceding paragraph help you group things.  Python uses the
fact that you're used to this kind of grouping process from reading in its
syntax -- that way your eye & brain read the same thing as the Python
compiler.
  
--david



From doughellmann@mindspring.com  Tue Mar  9 01:45:07 1999
From: doughellmann@mindspring.com (Doug Hellmann)
Date: Mon, 08 Mar 1999 20:45:07 -0500
Subject: [Tutor] Children of all ages
References: <002001be6974$803f2fa0$2e82f3d0@seigel.eico.com>
Message-ID: <36E47D21.B2178565@mindspring.com>

Hi, Art,

I agree with your comments on learning OOP by writing graphics apps. 
I'm not familiar with OpenGL, but I know that learning with something
like the Tk Canvas would be a good way to break into OOP and event based programming.

As far as your project with sockets, I'd suggest starting out with a
simple client/server setup.  The first program I wrote with sockets had
a server that would just print out whatever text the client sent.  Once
you can do that, you have the basics down for reading from the socket
without hanging using select().  If you are sending plain text back and
forth, you might send something that you have to parse (like a command
with parameters).  That means you have to accumulate enough data to make
the parsing work.

When you are comfortable with plain text, you can move on to something
like reading a fixed amount of data from the socket.  That lets you send
records or data structures.  Then you get into things like sending
binary data, which brings up topics like byte order.

If you want to play with select(), you could also start with the httplib
that comes with Python.  Using that, you can connect to any web server
and grab web pages.  The benefit of using HTTP is that you can check
your results against what your web browser gets.  Of course, httplib
hides the really interesting part of openning the socket, etc., but it
would be a good way to break into the client side.

Doug


From da@ski.org  Tue Mar  9 04:28:15 1999
From: da@ski.org (David Ascher)
Date: Mon, 8 Mar 1999 20:28:15 -0800 (Pacific Standard Time)
Subject: [Tutor] Children of all ages
In-Reply-To: <36E47D21.B2178565@mindspring.com>
Message-ID: <Pine.WNT.4.05.9903082027160.154-100000@david.ski.org>

> I agree with your comments on learning OOP by writing graphics apps. 
> I'm not familiar with OpenGL, but I know that learning with something
> like the Tk Canvas would be a good way to break into OOP and event based programming.

This reminds me - I recommend trying out the turtle.py module which Guido
put in Python 1.5.2b1 -- it's a great first step for logo-style graphics,
especially when driven in IDLE (the Interactive Development Environment,
also by Guido).

--david



From tim_one@email.msn.com  Tue Mar  9 07:54:17 1999
From: tim_one@email.msn.com (Tim Peters)
Date: Tue, 9 Mar 1999 02:54:17 -0500
Subject: [Tutor] RE: Tutor digest, Vol 1 #2 - 4 msgs
In-Reply-To: <001e01be698a$a960a880$0acb9284@dumyat.gssec.bt.co.uk>
Message-ID: <000f01be6a02$08131620$9b9e2299@tim>

[Alan Gauld]
> ...
> I've been programming for about 15 years in C, C++, awk,
> Smalltalk, Lisp and Delphi.(Oh and COBOL but I try to forget
> that...)
>
> Anyway, My point for a Python tutorial:
>
> Explain the colon!!! It gets a passing mention in Lutz's book,
> none at all in Watter's book. It took me (as an experienced
> programmer) at least half an hour to figure out how/when
> the colon should be used(mainly by browsing the demo code)
> a beginner to programming with no concept of a 'block of
> code' will be baffled IMHO.

Alan, it's probably your very *experience* that gets in the way here.  No
kidding!  The colons aren't syntactically necessary, and you're experienced
enough to at least inuit that.

Python's most direct predecessor was a language called ABC, designed at CWI
in the Netherlands (Guido's former employer, and where Python began too).
ABC was a research project aiming at computer first-timers, and all aspects
of its design were subject to formal usability studies.  After a few
iterations, what they discovered is that "begin/end" blocking constructs
confused complete newbies, but using indentation for blocking didn't --
provided that the block's opening line ended with a colon.  We can speculate
about *why* that might be (and David's analogy with outlines sounds good to
me -- except that outlines don't usually have colons <wink>), but the fact
is that's what the studies discovered empirically.

BTW, I can tell you from my own experience that you wouldn't like ABC.  It
catered to newcomers so relentlessly that many aspects of it plain got in
the way for experienced programmers.  The trailing colon isn't one of those,
though; over time I predict you'll grow quite fond of it.

historically y'rs  - tim




From M.Faassen@vet.uu.nl  Tue Mar  9 09:59:06 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Tue, 09 Mar 1999 10:59:06 +0100
Subject: [Tutor] RE: Tutor digest, Vol 1 #2 - 4 msgs
References: <Pine.WNT.4.04.9903081257470.254-100000@rigoletto.ski.org>
Message-ID: <36E4F0EA.6B3E1524@pop.vet.uu.nl>

David Ascher wrote:
> 
> On Mon, 8 Mar 1999, Martijn Faassen wrote:
> > Alan Gauld wrote:
> > > Explain the colon!!!
> >
> > I agree a beginner tutorial should have a good explanation of 'block
> > structure' in programming, though. In Python this is marked by the : and
> > an indented block, but saying 'explain the colon' mystifies me. :)
> 
> Let me try to emphasize that I'd much rather see explanations than
> defensive reactions.  If the questions are there, they indicate a need
> which isn't met.

Whoops. I didn't mean to send out a 'defensive reaction'. I genuinely
was puzzled by 'explain the colon' and it took me a second more careful
reading to get what was being talked about. Also it seemed that Alan
Gauld understood the concept just fine now, so I didn't venture an
explanation in response (though I agreed there ought to be one).

Independently (I haven't read David Ascher's response yet) here's my
attempt at block structure, if not for Alan then for posterity. :)

In an imperative computer language like Python and many others (don't
bother about what 'imperative' means right now), the concept of 'block
structure' is very important. A block of code is a sequence of
statements in a programming language that 'belongs together'. Generally
this means that whenever the first statement the block is executed, all
the other statements in the block will be executed as well, one by one.
There are exceptions to this rule in Python; I'll get to some of these
later.

A lot of programming language mark blocks by saying 'okay, here a block
begins', and 'here a block ends' by using special characters such as '{'
and '}'. In Python, the block structure is defined by:

a) a colon announcing that here a new block starts. Compare this to the
use of the colon in natural language, see for instance the colon in the
previous paragraph.

b) indentation (from the left side of the screen, using spaces (usually
4) or 'tab' characters). All statements in the block have the same
indentation, except those of blocks that are contained, which have
greater indentation.

An example (not in Python) of a block containing 3 statements:

my block:
    statement
    statement
    statement

A block may also contain other blocks inside them. This would look like
this:

my block:
    statement
    my subblock:
        statement
        statement
    statement
    statement

So, blocks can be used to structure a program. What would be the use of
this structuring capability? In Python, we can define functions, with
the statement 'def'. The statement 'def' announces a function definition
follows. First after 'def' Python expects a function name, then a list
of arguments marked by '(' and '), and finally a colon, announcing the
block that follows.

For instance:

# function without arguments (so the space between '(' and ')' is empty,
# to keep things simple
def print_stuff():
    print "Hello world."
    print "We are explaining block structure."
    print "We're done now."

Once you have this function and Python has processed it, it can be used
anywhere else in the program, just by calling it like this: 

    print_stuff()

This then makes Python execute the statements in the function
'print_stuff', and the result will be:

    Hello world.
    We are explaining block structure.
    We're done now.

A program that runs on straight forever can't do much; it can't respond
to changing circumstances in the outside world (the user or the data it
may be reading from disk or from a network). A program needs to be able
to behave differently in different circumstances. For this purpose we
have the 'if' statement, another great example of the use of block
structure. 'if' is always followed by a description of a condition (for
instance, the value of 'a' is smaller than that of 'b'). If the
condition happens to be the case (if the condition is 'true', in
programmer speak), then the block that follows is executed. If the
condition isn't the case or false, then the block that follows is
skipped and not executed. An example:

a = 3
b = 4
if a < b:
    print "'a' is smaller than 'b'."
    print "We put in another statement just to show we can."

If we execute this program, of course a (3) will always be smaller than
b (4), so we'll always get the output:

    'a' is smaller than 'b'.
    We put in another statement just to show we can.

(as you may have figured, a block can also just be just a single
statement; we don't need the second 'print' statement here :)

This is a trivial example. A more complicated example would not always
behave the same, as the value of a and b would depend on other things
(for instance they are the result of some calculation, involving data
that may be different each time this program is executed).

We can put blocks in blocks, as we saw before. An example (also of a
function with two arguments, called 'a' and 'b'):

def is_a_smaller_than_b(a, b):
    if a < b:
        print "Yes, a is smaller than b"
    print "We are done."

If you call this function like this:

    is_a_smaller_than_b(3, 4)

gets you the folllowing output:

    Yes, a is smaller than b
    We are done.

If we call it like this:

    is_a_smaller_than_b(100000, 1)

We get this output:

    We are done.

As the 'if' block was not executed.

Blocks are therefore a very useful and even essential way to structure
your Python programs. It is easy to recognize a block in Python; they're
always announced by a colon (:) and they are always indented.

Of course, I'm trying to explain too many basic things at once, so I may
have left posterity completely confused. If you happen to be completely
confused, feel free to ask questions about anything I talked about (or
things I didn't talk about :).

Regards,

Martijn


From alan.gauld@gssec.bt.co.uk  Tue Mar  9 17:37:01 1999
From: alan.gauld@gssec.bt.co.uk (Alan Gauld)
Date: Tue, 9 Mar 1999 17:37:01 -0000
Subject: [Tutor] RE: Tutor digest, Vol 1 #3 - 7 msgs
In-Reply-To: <199903091704.MAA24072@python.org>
Message-ID: <004e01be6a53$71064a20$0acb9284@dumyat.gssec.bt.co.uk>

> kidding!  The colons aren't syntactically necessary, and 
> you're experienced
> enough to at least inuit that.

Yes, That's possibly why I was confused. There seemed to 
be an essential syntactic element which served no 
practical use, so I kept asking - "What's it for?!"

Also I initially thought it was a line terminator
(like ; in Perl). My point was that nobody even *mentions* 
the colon in the existing tutorial or in Guido and Aarons 
book. Lutz gives it a passing mention in one sentence!

> iterations, what they discovered is that "begin/end" blocking 
> constructs
> confused complete newbies, but using indentation for blocking 
> didn't --
> provided that the block's opening line ended with a colon.  

Bizarre, but OK I can believe it... :-)

> though; over time I predict you'll grow quite fond of it.

After about 3 months I still miss it out. :-(

But at least I now recognise immediately what the 
problem is....

Thanks for all the responses, at least it got a thread going :-)

Alan G.


From alan.gauld@gssec.bt.co.uk  Tue Mar  9 17:40:38 1999
From: alan.gauld@gssec.bt.co.uk (Alan Gauld)
Date: Tue, 9 Mar 1999 17:40:38 -0000
Subject: [Tutor] RE: Tutor digest, Vol 1 #3 - 7 msgs
In-Reply-To: <199903091704.MAA24072@python.org>
Message-ID: <004f01be6a53$f248ce00$0acb9284@dumyat.gssec.bt.co.uk>

> Whoops. I didn't mean to send out a 'defensive reaction'. I
genuinely
> was puzzled by 'explain the colon' and it took me a second

No offense taken here - I've been on usenet too long for that :-)

> Independently (I haven't read David Ascher's response yet)
here's my
> attempt at block structure, if not for Alan then for posterity.
:)

And a really fine attempt it is too (well, I understood it :)
Now if we can collect snippets like that we can pretty quickly
get a
real newbie tutorial sorted.

Alan G.



From alex_c@MIT.EDU  Tue Mar  9 18:16:10 1999
From: alex_c@MIT.EDU (Alexander S Coventry)
Date: Tue, 9 Mar 1999 13:16:10 -0500 (EST)
Subject: [Tutor] RE: Tutor digest, Vol 1 #3 - 7 msgs
In-Reply-To: <004e01be6a53$71064a20$0acb9284@dumyat.gssec.bt.co.uk>
 (alan.gauld@gssec.bt.co.uk)
References: <004e01be6a53$71064a20$0acb9284@dumyat.gssec.bt.co.uk>
Message-ID: <199903091816.NAA00414@mass-toolpike.mit.edu>

> After about 3 months I still miss it out. :-(

So do I, actually.  I find using emacs' python-mode a little helpful
in this respect, because missing one, or forgetting to close a
parenthesis screws up all the subsequent indentation.

Alex.


From joe@strout.net  Tue Mar  9 18:37:12 1999
From: joe@strout.net (Joseph J. Strout)
Date: Tue, 9 Mar 1999 10:37:12 -0800
Subject: [Tutor] RE: Tutor digest, Vol 1 #3 - 7 msgs
In-Reply-To: <199903091816.NAA00414@mass-toolpike.mit.edu>
References: <004e01be6a53$71064a20$0acb9284@dumyat.gssec.bt.co.uk>
 (alan.gauld@gssec.bt.co.uk)
 <004e01be6a53$71064a20$0acb9284@dumyat.gssec.bt.co.uk>
Message-ID: <v04020a0bb30b1ac29995@[198.202.70.213]>

At 10:16 AM -0800 03/09/99, Alexander S Coventry wrote:
>> After about 3 months I still miss it out. :-(
>
>So do I, actually.  I find using emacs' python-mode a little helpful
>in this respect, because missing one, or forgetting to close a
>parenthesis screws up all the subsequent indentation.

FWIW, the same is true for the MacPython IDE.

Cheers,
-- Joe
,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'


From ajs@ix.netcom.com  Tue Mar  9 18:45:54 1999
From: ajs@ix.netcom.com (Art Siegel)
Date: Tue, 9 Mar 1999 13:45:54 -0500
Subject: [Tutor] Malloc, bitwise operations and other nasties
Message-ID: <000d01be6a5d$11515c00$2e82f3d0@seigel.eico.com>

This is a multi-part message in MIME format.

------=_NextPart_000_000A_01BE6A33.273C6B60
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable


I am retransmitting the following. I apologize if duplicated.


The following is a code snippet from OpenGL demo code I am trying to =
port to Python.=20
/* Create a single component texture map */=20
GLfloat *=20
make_texture(int maxs, int maxt)=20
{=20
int s, t;=20
static GLfloat *texture;=20
texture =3D (GLfloat *) malloc(maxs * maxt * sizeof(GLfloat));=20
for (t =3D 0; t < maxt; t++) {=20
for (s =3D 0; s < maxs; s++) {=20
texture[s + maxs * t] =3D ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);=20
}=20
}=20
return texture;=20
}
The code creates a checkerboard texture, which gets mapped to an object.
Between the malloc call (something to do with memory, I know) and the =
bitwise operators, I am lost.
I certainly can't see how this becomes a texturemap.
If I saw the code in Pythonese, I couldl probably begin to understand =
it.=20
Any help is appreciated.



------=_NextPart_000_000A_01BE6A33.273C6B60
Content-Type: text/html;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML//EN">
<HTML>
<HEAD>

<META content=3Dtext/html;charset=3Diso-8859-1 =
http-equiv=3DContent-Type>
<META content=3D'"MSHTML 4.72.3110.7"' name=3DGENERATOR>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT color=3D#000000 size=3D2>I am retransmitting the following. I =
apologize=20
if duplicated.</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>The following is a code snippet from OpenGL demo code I am trying =
to port=20
to Python. </DIV>
<DIV>/* Create a single component texture map */ </DIV>
<DIV>GLfloat * </DIV>
<DIV>make_texture(int maxs, int maxt) </DIV>
<DIV>{ </DIV>
<DIV>int s, t; </DIV>
<DIV>static GLfloat *texture; </DIV>
<DIV>texture =3D (GLfloat *) malloc(maxs * maxt * sizeof(GLfloat)); =
</DIV>
<DIV>for (t =3D 0; t &lt; maxt; t++) { </DIV>
<DIV>for (s =3D 0; s &lt; maxs; s++) { </DIV>
<DIV>texture[s + maxs * t] =3D ((s &gt;&gt; 4) &amp; 0x1) ^ ((t &gt;&gt; =
4) &amp;=20
0x1); </DIV>
<DIV>} </DIV>
<DIV>} </DIV>
<DIV>return texture; </DIV>
<DIV>}</DIV>
<DIV>The code creates a checkerboard texture, which gets mapped to an=20
object.</DIV>
<DIV>Between the malloc call (something to do with memory, I know) and =
the=20
bitwise operators, I am lost.</DIV>
<DIV>I certainly can't see how this becomes a texturemap.</DIV>
<DIV>If I saw the code in Pythonese, I couldl probably begin to =
understand it.=20
</DIV>
<DIV>Any help is appreciated.</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;</DIV></DIV></BODY></HTML>

------=_NextPart_000_000A_01BE6A33.273C6B60--



From da@ski.org  Tue Mar  9 19:14:26 1999
From: da@ski.org (David Ascher)
Date: Tue, 9 Mar 1999 11:14:26 -0800 (Pacific Standard Time)
Subject: [Tutor] Malloc, bitwise operations and other nasties
In-Reply-To: <000d01be6a5d$11515c00$2e82f3d0@seigel.eico.com>
Message-ID: <Pine.WNT.4.04.9903091055330.283-100000@rigoletto.ski.org>

On Tue, 9 Mar 1999, Art Siegel wrote:

> The following is a code snippet from OpenGL demo code I am trying to
> port to Python.

> /* Create a single component texture map */ 
> GLfloat * 
> make_texture(int maxs, int maxt) 
> { 
> int s, t; 
> static GLfloat *texture; 
> texture = (GLfloat *) malloc(maxs * maxt * sizeof(GLfloat)); 
> for (t = 0; t < maxt; t++) { 
> for (s = 0; s < maxs; s++) { 
> texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1); 
> } 
> } 
> return texture; 
> }
> The code creates a checkerboard texture, which gets mapped to an object.
> Between the malloc call (something to do with memory, I know) and the bitwise operators, I am lost.
> I certainly can't see how this becomes a texturemap.
> If I saw the code in Pythonese, I couldl probably begin to understand it. 
> Any help is appreciated.

This is a great example of why C is ugly =)

malloc creates an array of unitialized bytes.  A close equivalent to the
above code in Python would be

texture = [0.0]*(maxs*maxt)
for t in range (maxt):
  for s in range(maxs):
    texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1); 


If you try it with maxs and maxt set to 20, you'll see the 'scan lines':

>>> maxt = maxs = 20
>>> texture = [0.0]*(maxs*maxt)
>>> for t in range (maxt):
...   for s in range(maxs):
...     texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);
...
>>> print texture
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
1, 1, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1 , 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 0, 0, 0, 0]

However, looking at it like that makes it a bit hard to see how it works.
One could recode it as:

>>> texture = []
>>> for t in range (maxt):
...    line = []              # note we're using lists of lists
...    texture.append(line)   # to make the 'lines'
...    for s in range(maxs):
...       line.append(((s >> 4) & 0x1) ^ ((t >> 4) & 0x1))
...
>>> texture
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], 
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], 
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
]

(this looks if you try like the corner of a checkerboard)

How does it work?  The key is clearly the 

  ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);

s >> 4 is the value of s, shifted to the right by four bits.  When AND'ed
with 1, that tests whether the bit four bits from the right in s is on or
not.  When OR'ed with the equivalent for t, that will be 1 if either the
fourth bit in s or the fourth bit in t are on (or both).  Which means that
columns 16 through 31 and rows 16 through 31 will be "on", and columns 0
through 15 and rows 0 through 15 will be 'off' (with that pattern repeated
ad infinitum).  So the "4" in the right-shift operation determines the
"coarseness" of the texture.  The bit at the '4th position from the right'
is the bit corresponding to 2 to the fourth, or 16.  So in this case the
checkerboard is 16-off, 16-on.  If you make it 5, you'll get 32x32
checkerboards, etc.  

[I'm not happy about this discussion of bit-shifting -- anyone got better
 words to describe binary representations? -- say, Tim, where's that
 module of yours again?]

[To use this lists of lists in PyOpenGL you'll have to flatten it first,
 as per our discussion on the PyOpenGL list, until the next release]

Make sense?

--david




From ajs@ix.netcom.com  Tue Mar  9 19:46:52 1999
From: ajs@ix.netcom.com (Art Siegel)
Date: Tue, 9 Mar 1999 14:46:52 -0500
Subject: [Tutor] Malloc, bitwise operations and other nasties
Message-ID: <000401be6a65$959ba800$2e82f3d0@seigel.eico.com>

>Make sense?
>

 A bit. Or a byte. Probably more when I have a chance to play with it..
>_______________________________________________
>Tutor maillist  -  Tutor@python.org
>http://www.python.org/mailman/listinfo/tutor
>
>



From jlcos@accessone.com  Tue Mar  9 20:50:34 1999
From: jlcos@accessone.com (Jon Cosby)
Date: Tue, 9 Mar 1999 12:50:34 -0800
Subject: [Tutor] Tkinter
Message-ID: <01be6a6e$7ac796c0$0100007f@localhost>

This is a multi-part message in MIME format.

------=_NextPart_000_0004_01BE6A2B.6CA456C0
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

I need some help with Tkinter, and find the Pythonware tutorial to be =
lacking. I'd like create a button to call an application and dialog =
window for input, and present the results. Are there some good examples =
to look at to get me started?

Jon Cosby

------=_NextPart_000_0004_01BE6A2B.6CA456C0
Content-Type: text/html;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML//EN">
<HTML>
<HEAD>

<META content=3Dtext/html;charset=3Diso-8859-1 =
http-equiv=3DContent-Type>
<META content=3D'"MSHTML 4.71.1712.3"' name=3DGENERATOR>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT color=3D#000000 size=3D2>I need some help with Tkinter, and =
find the=20
Pythonware tutorial to be lacking. I'd like create a button to call an=20
application and dialog window for input, and present the results. Are =
there some=20
good examples to look at to get me started?</FONT></DIV>
<DIV><FONT color=3D#000000 size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT color=3D#000000 size=3D2>Jon Cosby</FONT></DIV></BODY></HTML>

------=_NextPart_000_0004_01BE6A2B.6CA456C0--



From geek+@cmu.edu  Tue Mar  9 21:25:07 1999
From: geek+@cmu.edu (geek+@cmu.edu)
Date: 9 Mar 1999 16:25:07 -0500
Subject: [Tutor] Tkinter
In-Reply-To: <01be6a6e$7ac796c0$0100007f@localhost>
Message-ID: <emacs-smtp-22924-14053-37299-470004@export.andrew.cmu.edu>

--pgp-sign-Multipart_Tue_Mar__9_16:25:06_1999-1
Content-Type: text/plain; charset=US-ASCII

Then <jlcos@accessone.com> spoke up and said:
> I need some help with Tkinter, and find the Pythonware tutorial to be =
> lacking. I'd like create a button to call an application and dialog =
> window for input, and present the results. Are there some good examples =
> to look at to get me started?

Firstly, *please* disable sending mail as HTML.

Next, I've always found that the best place to look for doing Tkinter
things is in the DEMO directory of the source distribution.
Unfortunately, there really are no "good" examples.  

One trick that sometimes works for me is to design something in
Tcl/Tk, and then translate it into Tkinter.  Of course, you end up
working twice as hard, and if you use a tool like SpecTCL, the
translation step can be painful.  

Speaking of SpecTCL, there is a plugin for it called SpecPYTHON that
(theoretically) lets you design Tkinter apps and spits out Python
code.  Unfortunately, getting it all working is non-trivial.

I almost forgot: don't forget to look at the source in
/usr/local/lib/python1.5/lib-tk/*.py.  While somewhat minimal, most of
the source files there include test functions that show small,
low-level uses of the various widgets.

Beyond that, you have to get really specific.  The most generic advice
to give is this:  Learn how to use and write factory functions.  They
are your friends.  e.g

import Tkinter

def foo():
	pass

def button_factory(master, command=None):
	b = Tkinter.Button(t, background='red', command)
	b.pack(side=Tkinter.LEFT)
	return b

t = Tkinter.Toplevel()
t.b1 = button_factory(t, command=foo)

While the above example is *really* trivial, if you have a more
exciting set of attributes that need to be set for every button, the
factory function will become very handy (and even more readable).

Does this answer your question (at least in part)?


-- 
=====================================================================
| JAVA must have been developed in the wilds of West Virginia.      |
| After all, why else would it support only single inheritance??    |
=====================================================================
| Finger geek@andrew.cmu.edu for my public key.                     |
=====================================================================

--pgp-sign-Multipart_Tue_Mar__9_16:25:06_1999-1
Content-Type: application/pgp-signature
Content-Transfer-Encoding: 7bit

-----BEGIN PGP MESSAGE-----
Version: 2.6.2
Comment: Processed by Mailcrypt 3.3, an Emacs/PGP interface

iQBVAwUBNuWRs4dzVnzma+gdAQGB3QH+LnwMLgl2Sf/hCy4pGHdJH1kv0jxHrRpu
HblyPTlVXLLmSHVhBOmOvw1OavoPCANdWP8S3dXBt+cButD3RnAuEA==
=pMqB
-----END PGP MESSAGE-----

--pgp-sign-Multipart_Tue_Mar__9_16:25:06_1999-1--



From tim_one@email.msn.com  Wed Mar 10 09:27:08 1999
From: tim_one@email.msn.com (Tim Peters)
Date: Wed, 10 Mar 1999 04:27:08 -0500
Subject: [Tutor] Malloc, bitwise operations and other nasties
In-Reply-To: <Pine.WNT.4.04.9903091055330.283-100000@rigoletto.ski.org>
Message-ID: <001301be6ad8$2b054b40$9b9e2299@tim>

[David Ascher]
> ...
> [I'm not happy about this discussion of bit-shifting -- anyone got better
>  words to describe binary representations?

The 1 bits are foxes, the 0 bits are chickens, shifting right is when the
foxes chase the chickens to the east except some fall off the end of the
Earth, and xor is the well-known rule that a fox and a chicken in the same
coop at the same time leaves only the fox, will two foxes together devour
each other and two chickens together bore each other out of existence.
There!  I hope you're a lot happier about *your* discussion now <wink>

> -- say, Tim, where's that module of yours again?]

tabnanny.py is in Tools/Scripts/, of course.

playing-it-straight-ly y'rs  - tim




From GBCGOLF@aol.com  Wed Mar 10 18:45:42 1999
From: GBCGOLF@aol.com (GBCGOLF@aol.com)
Date: Wed, 10 Mar 1999 13:45:42 EST
Subject: [Tutor] Python Picture
Message-ID: <e64df7e3.36e6bdd6@aol.com>

I'm finishing a "beginners" paper on Python (i.e.: please have mercy, I'm a
newbie.)  I would like to put the "Python" symbol (prefer full snake icon over
snake head icon) on the first page of a MS Word (Office 97) document.  Is that
possible?  If so, how.  I need to turn in the paper this evening so I may have
posted this question too late for a response.  Thanks much for any info.
Beth


From joe@strout.net  Wed Mar 10 18:56:45 1999
From: joe@strout.net (Joseph J. Strout)
Date: Wed, 10 Mar 1999 10:56:45 -0800
Subject: [Tutor] Python Picture
In-Reply-To: <e64df7e3.36e6bdd6@aol.com>
Message-ID: <v04020a06b30c704b7c03@[198.202.70.213]>

At 10:45 AM -0800 03/10/99, GBCGOLF@aol.com wrote:

>I'm finishing a "beginners" paper on Python (i.e.: please have mercy, I'm a
>newbie.)  I would like to put the "Python" symbol (prefer full snake icon over
>snake head icon) on the first page of a MS Word (Office 97) document.

Hi Beth,

Python's proper symbol is not a snake, but a 16-ton falling weight.  From
the documentation (section 1.4): "By the way, the language is named after
the BBC show ``Monty Python's Flying Circus'' and has nothing to do with
nasty reptiles..."

Cheers,
-- Joe
,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'


From da@ski.org  Wed Mar 10 19:18:24 1999
From: da@ski.org (David Ascher)
Date: Wed, 10 Mar 1999 11:18:24 -0800 (Pacific Standard Time)
Subject: [Tutor] Python Picture
In-Reply-To: <v04020a06b30c704b7c03@[198.202.70.213]>
Message-ID: <Pine.WNT.4.04.9903101115480.259-100000@rigoletto.ski.org>

On Wed, 10 Mar 1999, Joseph J. Strout wrote:
> 
> >I'm finishing a "beginners" paper on Python (i.e.: please have mercy, I'm a
> >newbie.)  I would like to put the "Python" symbol (prefer full snake icon over
> >snake head icon) on the first page of a MS Word (Office 97) document.
> 
> Hi Beth,
> 
> Python's proper symbol is not a snake, but a 16-ton falling weight.  From
> the documentation (section 1.4): "By the way, the language is named after
> the BBC show ``Monty Python's Flying Circus'' and has nothing to do with
> nasty reptiles..."

That said, I think she can use a snake if all the book publishers do. =)

As to how that should be done, what I'd do if I were you Beth is to take a
snapshot of the screen (with the Control-PrintScreen key combination), go
to a bitmap editor (you should have one called "Paint" under your
Accessories menu under Program under the Start menu), and paste the new
picture into it -- then use the rectangle selection tool to isolate the
part of the screen you want to use, copy that, and paste that into word.
Should work.

permissively-yrs,

--david



From tismer@appliedbiometrics.com  Wed Mar 10 19:29:54 1999
From: tismer@appliedbiometrics.com (Christian Tismer)
Date: Wed, 10 Mar 1999 20:29:54 +0100
Subject: [Tutor] Python Picture
References: <e64df7e3.36e6bdd6@aol.com>
Message-ID: <36E6C832.89667F02@appliedbiometrics.com>

This is a multi-part message in MIME format.
--------------F4D90759C6B207B0323C932E
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit



GBCGOLF@aol.com wrote:
> 
> I'm finishing a "beginners" paper on Python (i.e.: please have mercy, I'm a
> newbie.)  I would like to put the "Python" symbol (prefer full snake icon over
> snake head icon) on the first page of a MS Word (Office 97) document.  Is that
> possible?  If so, how.  I need to turn in the paper this evening so I may have
> posted this question too late for a response.  Thanks much for any info.
> Beth

You mean the icons from PythonWin, and these are .ico files.
You can of course turn it into a graphics format which
Word will accept. There are several ways to do that.
Assuming you have the Office 97 full tool set, there is the
Microsoft Photo editor as well.

Here is a brute force attack :-)

Open an Explorer Window in a directory with a couple of .py files.
Change the display (view menu) to "big symbols" and scroll until
you have some nice Pythons in sight.
Hold alt-shift down and press the print key.
This gives you a snapshot of the current window in the clipboard.
Now open the Photo editor, and select "edit - insert as picture"
(maybe slightly different, my German version reads
"bearbeiten - als neues Bild einfügen".
Having done that, you have the screenshot in the Photo Editor.

Now zoom to 800%, use the selection tool and capture a 
Python. 32x32 pixels should be the exact result, or something is 
wrong.
Now use edit - copy to copy this selection into the clipbord.
Create another picture which is your Python cutout, again with
the "insert as picture" operation.
Now save the file in a format as you like. BMP will work,
GIF is ok as well. You can also leave it in Photo Editor
format since Word can display it. Just open Word and insert
the graphic object from the clipboard.

Note that a JPeg version with 90% quality looks better for me
than the original.

Note also that the same procedure is possible with a number
of other graphic editors like Paintshop Pro or Adobe Photoshop.
In Photoshop, you would simply select the 32x32 range and use
image/crop to adjust the size.

Alternatively, you can grab such a Python from the internet.
See http://starship.python.net/crew/skippy/ where you will
find an animated Python gif from Mark Hammond. But I doubt
that it will stay animated in the Word document,
at least not after printing :-)

have fun - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home
--------------F4D90759C6B207B0323C932E
Content-Type: image/jpeg;
 name="python.jpg"
Content-Transfer-Encoding: base64
Content-Disposition: inline;
 filename="python.jpg"

/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoM
DAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsN
FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAAR
CAAgACADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAA
AgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkK
FhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWG
h4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl
5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREA
AgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYk
NOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE
hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk
5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD6p/4KF+M7PSPht4a8K3fi+PwxB4o1K6t7
23XVrPTZtRtINNvLj7N510jxxwyXMdlDIzKVKziN8rKVb8/fhX48b4HfEnwF4u07V7kR22n6
PN4q16PULPUZ7a23aet/YS2lpCJraCCGS7iW2uRIVFlEYQhtgR1WhaJ4p8Sg+KfEl7aXHi3V
ik+v3F7F5d81wkLrLbzZYeXJDOkibNoWFU8lUQJlcm0+JHg7UbrUztg1zwZpcM39t+ILlilg
jK2wW8Ssh+1s29Cyr8uGXa0hkVD+QYziaVTHTlh8PzqnZbzTTUr30lGPM7OCjJSUlJ6OXI4f
PYriPLsNRk6UnVmr+7BXd+zbso+V2m2rJN3T/XjwV8QvCvxK0qXU/CHibR/FWmxTG2kvNEv4
ryFJQqsYy8bMAwV0O3OcMD3FdBX48eGfE2tfAS7t/iHZbodZ0VZb3alyrzXekpO8p0y4mG8O
GhXymZvNCygTKXdEc/sPX6Dk+b0s4pSqU1Zxdnrf5p9Uz3KNWGIowr03eMldf5PfVbPzPzO/
aP8A2VdY8ZfEz4tfF3xPoPh7RPD16bKC5HiLxFeWc4jSztEWOP7JZTecZD5cRSF23TGSJfNw
jHi7fSvD2geH7jTdKaO70W+0y4slkl0aPTlMc0rxTmwsld2slntAY5Jrl5bki6mEYs2EiP8A
dX7ZngnxJ4y+GWkSeH4LvUbfRdai1fVdK08eZcX1rHBOAscOCJ3jne3uBGfmJtwYw0qxq3wV
9p0/4r6xLpng+/8A+Ey1e7hVP7L8OzfarxQcRB2e3JWBNxQGeR444zIm50yDXwvEjxWGxkKW
Dpycp68/vSad7WgtYwdrXaSdnbQ8PO8Ysdm9CjWi6dPkXK4uclFqy5acWpRpuWsp1F7z5nqp
zUzuf2cfAmjftNfFa40vUPEWkS6T4cljudV0f7ZDNeagIZI2+yC2YsxtdzRpcSyKUYSGEbne
RoPtzxv+1b8LPBPwn1f4ijxjpfiLw3p0j23meG7yLUJLm6WLzfssIjchptnzlSQFTLuVRWcf
nuPgp4v1C6Tw1YfDbxW+oW/mWsemjRLixgRRG8csIvZAll5ZiMsbYuDFKjNGrSrIFf3Xwz/w
Tn1PVPFdjJ481LQL7QrixC6tJo0csV7KhOX0pXZcmAnlrsPG7LuVbeF2WZPV4fliMJhlhsPg
pRs/ecny66a2aTa8ltZJNts9ujKgqUY4eLUI6JcrjZekraelz//Z
--------------F4D90759C6B207B0323C932E
Content-Type: image/gif;
 name="python.gif"
Content-Transfer-Encoding: base64
Content-Disposition: inline;
 filename="python.gif"

R0lGODdhIAAgAPcAAAAAAAAAVQAAqgAA/wAkAAAkVQAkqgAk/wBJAABJVQBJqgBJ/wBtAABt
VQBtqgBt/wCSAACSVQCSqgCS/wC2AAC2VQC2qgC2/wDbAADbVQDbqgDb/wD/AAD/VQD/qgD/
/yQAACQAVSQAqiQA/yQkACQkVSQkqiQk/yRJACRJVSRJqiRJ/yRtACRtVSRtqiRt/ySSACSS
VSSSqiSS/yS2ACS2VSS2qiS2/yTbACTbVSTbqiTb/yT/ACT/VST/qiT//0kAAEkAVUkAqkkA
/0kkAEkkVUkkqkkk/0lJAElJVUlJqklJ/0ltAEltVUltqklt/0mSAEmSVUmSqkmS/0m2AEm2
VUm2qkm2/0nbAEnbVUnbqknb/0n/AEn/VUn/qkn//20AAG0AVW0Aqm0A/20kAG0kVW0kqm0k
/21JAG1JVW1Jqm1J/21tAG1tVW1tqm1t/22SAG2SVW2Sqm2S/222AG22VW22qm22/23bAG3b
VW3bqm3b/23/AG3/VW3/qm3//5IAAJIAVZIAqpIA/5IkAJIkVZIkqpIk/5JJAJJJVZJJqpJJ
/5JtAJJtVZJtqpJt/5KSAJKSVZKSqpKS/5K2AJK2VZK2qpK2/5LbAJLbVZLbqpLb/5L/AJL/
VZL/qpL//7YAALYAVbYAqrYA/7YkALYkVbYkqrYk/7ZJALZJVbZJqrZJ/7ZtALZtVbZtqrZt
/7aSALaSVbaSqraS/7a2ALa2Vba2qra2/7bbALbbVbbbqrbb/7b/ALb/Vbb/qrb//9sAANsA
VdsAqtsA/9skANskVdskqtsk/9tJANtJVdtJqttJ/9ttANttVdttqttt/9uSANuSVduSqtuS
/9u2ANu2Vdu2qtu2/9vbANvbVdvbqtvb/9v/ANv/Vdv/qtv///8AAP8AVf8Aqv8A//8kAP8k
Vf8kqv8k//9JAP9JVf9Jqv9J//9tAP9tVf9tqv9t//+SAP+SVf+Sqv+S//+2AP+2Vf+2qv+2
///bAP/bVf/bqv/b////AP//Vf//qv///yH5BAAAAAAALAAAAAAgACAAQAj/AP8JHPgPAICC
BgkqXLjQICQ2DyNChAhgYkKGCg0CAAdOIyQOHA4CAMlB4kGMGUmymfgQgMmCEQ1SzMhvAICa
NtmcRNmQJRs4jDjAAWmQZMWXGDlqvFiQpERIO3kOHEmSAyOJJX1CFcg041KDcHRKlXqTX1mz
UKOOPeqTEdChQYmyVEuQalWiBuPafbiSbl2OHNgYPUnVrdutPMHVtfsTYli/izNGDAzpKiM2
V59OdIsZst2hF7+OrUvxMuLRGMuerQgZ9U2bOAHAab1Wo868LTW61grp7c+gshvTdulS52/B
H6sCsHy6IUjkVgeXDBk47GOUIz8Knl1UsMyPlSsPS9/YcblRrkMnzpYKeDDXh1aRJv2nOCPQ
5/JT94Qf1qRurqGJVVdVzOkESURuLRcWZy2lRBIc1j30lmZFhZQaRHFJpxxtDS2FmkIBAQA7

--------------F4D90759C6B207B0323C932E--



From da@ski.org  Wed Mar 10 22:56:21 1999
From: da@ski.org (David Ascher)
Date: Wed, 10 Mar 1999 14:56:21 -0800 (Pacific Standard Time)
Subject: [Tutor] "Instant Hacking" - programming intro (fwd)
Message-ID: <Pine.WNT.4.04.9903101456030.259-100000@rigoletto.ski.org>

FYI:

---------- Forwarded message ----------
Date: Wed, 10 Mar 99 22:00:55 GMT
From: Magnus L. Hetland <mlh@idt.ntnu.no>
To: python-announce-list@cwi.nl
Newsgroups: comp.lang.python, comp.lang.python.announce
Subject: "Instant Hacking" - programming intro

I have made (or am making...) a small programming tutorial with Python
as the example language. It is available from my Python page

  http://www.idi.ntnu.no/~mlh/python/

as "Instant Hacking". It is a work in progress - comments and
suggestions are highly appreciated.

== 

  Magnus
  Lie
  Hetland        http://arcadia.laiv.org <arcadia@laiv.org>



From cyberjet@cheerful.com  Thu Mar 11 00:18:43 1999
From: cyberjet@cheerful.com (John E. Tobler)
Date: Wed, 10 Mar 1999 18:18:43 -0600
Subject: [Tutor] Python Picture
References: <v04020a06b30c704b7c03@[198.202.70.213]>
Message-ID: <36E70BE3.E5C1118A@omaha.crosswinds.net>

Joseph J. Strout remarked:
> Python's proper symbol is not a snake, 
> but a 16-ton falling weight.  

Just for the record, where can we find an official image of that 16-ton falling
weight?  

John Tobler
cyberjet@cheerful.com


From joe@strout.net  Thu Mar 11 00:35:54 1999
From: joe@strout.net (Joseph J. Strout)
Date: Wed, 10 Mar 1999 16:35:54 -0800
Subject: [Tutor] Python Picture
In-Reply-To: <36E70BE3.E5C1118A@omaha.crosswinds.net>
References: <v04020a06b30c704b7c03@[198.202.70.213]>
Message-ID: <v04020a08b30cc057e999@[198.202.70.213]>

At 4:18 PM -0800 03/10/99, John E. Tobler wrote:

>Just for the record, where can we find an official image of that 16-ton
>falling
>weight?

It's nothing official, but here's the one used with MacPython:

	http://www.strout.net/python/

Cheers,
-- Joe
,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'


From doughellmann@mindspring.com  Thu Mar 11 02:37:41 1999
From: doughellmann@mindspring.com (Doug Hellmann)
Date: Wed, 10 Mar 1999 21:37:41 -0500
Subject: [Tutor] Tkinter
References: <01be6a6e$7ac796c0$0100007f@localhost>
Message-ID: <36E72C72.AF697EB@mindspring.com>

Hi, Jon,

I have been going through the Tk/Tkinter learning curve over the past 6
months.  It took a little while to get up to speed, but now I'm writing
my own Python Mega Widgets (Pmw - http://www.dscpl.com.au/pmw/) -- check
out my widgets at http://www.mindspring.com/~doughellmann/Projects/PmwContribD.

Of course, that doesn't help with your question.  It isn't clear whether
you are having trouble with Tkinter, or Tk, or both.  What sort of
GUI/Tk/Python background do you have?  I was learning both Tk and
Tkinter at the same time (though at least I was already fairly fluent
with Python).  I found _Practical Programming in Tcl and Tk_ useful as a
good Tcl/Tk book.  It helped to translate some of the examples in to
Python, as exercises.

For creating a dialog, I would start by looking at the SimpleDialog.py
source file in your Python distribution.  The __init__ method shows how
to create a dialog which will respond to different button presses.  You
probably don't need to worry about all of the geometry management stuff
at first.  If you want the user to be able to enter a value, take a look
at the Entry widget -- the basic text field widget for getting simple
values from the user.

Pmw has some canned classes to do these sorts of things, and you can
look at that code too.  Since there is a lot of Pmw-specific overhead
though, that might be more confusing.

Doug

> Jon Cosby wrote:
> 
> I need some help with Tkinter, and find the Pythonware tutorial to be
> lacking. I'd like create a button to call an application and dialog
> window for input, and present the results. Are there some good
> examples to look at to get me started?
> 
> Jon Cosby


From phil@media-1.ml.uwcm.ac.uk  Thu Mar 11 09:42:42 1999
From: phil@media-1.ml.uwcm.ac.uk (Phil Harris)
Date: Thu, 11 Mar 1999 09:42:42 -0000
Subject: [Tutor] Python Picture
Message-ID: <003f01be6ba3$82b035a0$5c773fc1@media1>

And now, the easy way to convert ico files to bitmaps.

Open windows explorer, hilite the file to be converted, and rename it, the
file is automaticaly converted by Windows.

Easy when you know how eh!


----- Original Message -----
From: Christian Tismer <tismer@appliedbiometrics.com>
To: <GBCGOLF@aol.com>
Cc: <tutor@python.org>
Sent: Wednesday, March 10, 1999 7:29 PM
Subject: Re: [Tutor] Python Picture




GBCGOLF@aol.com wrote:
>
> I'm finishing a "beginners" paper on Python (i.e.: please have mercy, I'm
a
> newbie.)  I would like to put the "Python" symbol (prefer full snake icon
over
> snake head icon) on the first page of a MS Word (Office 97) document.  Is
that
> possible?  If so, how.  I need to turn in the paper this evening so I may
have
> posted this question too late for a response.  Thanks much for any info.
> Beth

You mean the icons from PythonWin, and these are .ico files.
You can of course turn it into a graphics format which
Word will accept. There are several ways to do that.
Assuming you have the Office 97 full tool set, there is the
Microsoft Photo editor as well.

Here is a brute force attack :-)

Open an Explorer Window in a directory with a couple of .py files.
Change the display (view menu) to "big symbols" and scroll until
you have some nice Pythons in sight.
Hold alt-shift down and press the print key.
This gives you a snapshot of the current window in the clipboard.
Now open the Photo editor, and select "edit - insert as picture"
(maybe slightly different, my German version reads
"bearbeiten - als neues Bild einfügen".
Having done that, you have the screenshot in the Photo Editor.

Now zoom to 800%, use the selection tool and capture a
Python. 32x32 pixels should be the exact result, or something is
wrong.
Now use edit - copy to copy this selection into the clipbord.
Create another picture which is your Python cutout, again with
the "insert as picture" operation.
Now save the file in a format as you like. BMP will work,
GIF is ok as well. You can also leave it in Photo Editor
format since Word can display it. Just open Word and insert
the graphic object from the clipboard.

Note that a JPeg version with 90% quality looks better for me
than the original.

Note also that the same procedure is possible with a number
of other graphic editors like Paintshop Pro or Adobe Photoshop.
In Photoshop, you would simply select the 32x32 range and use
image/crop to adjust the size.

Alternatively, you can grab such a Python from the internet.
See http://starship.python.net/crew/skippy/ where you will
find an animated Python gif from Mark Hammond. But I doubt
that it will stay animated in the Word document,
at least not after printing :-)

have fun - chris

--
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home

----------------------------------------------------------------------------
----




----------------------------------------------------------------------------
----






From tismer@appliedbiometrics.com  Thu Mar 11 10:12:51 1999
From: tismer@appliedbiometrics.com (Christian Tismer)
Date: Thu, 11 Mar 1999 11:12:51 +0100
Subject: [Tutor] Python Picture
References: <003f01be6ba3$82b035a0$5c773fc1@media1>
Message-ID: <36E79723.879FA05D@appliedbiometrics.com>


Phil Harris wrote:
> 
> And now, the easy way to convert ico files to bitmaps.
> 
> Open windows explorer, hilite the file to be converted, and rename it, the
> file is automaticaly converted by Windows.
> 
> Easy when you know how eh!

Did you ever test it? 3-[

I did, and it doesn't work, at least not with my Win98 standard setup.

I think you should stand in the corner, or I'm dumb.  <|:)

Way out of the corner:
Tell us what you installed to get the autoconversion,
and please send me a converted py.ico file which 
is recognized by word :-)

Well, I know there are some auto conversions available.
Versions of WinZip know to convert a .zip file into
a self extractor after you simply rename the file.
But this is dependent of the availability of a converter,
and I doubt this is installed by default for .ico files.

renaming_.py_to_.exe_is_easier_than_freeze - ly y'rs chris.ico

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home


From phil@media-1.ml.uwcm.ac.uk  Thu Mar 11 10:22:08 1999
From: phil@media-1.ml.uwcm.ac.uk (Phil Harris)
Date: Thu, 11 Mar 1999 10:22:08 -0000
Subject: [Tutor] Python Picture
Message-ID: <005901be6ba9$04c643e0$5c773fc1@media1>

I stand converted 8^(

I'm sure this used to work, hmm, I hate it when I'm wrong.

Apologies all round 8^)

Phil

----- Original Message -----
From: Christian Tismer <tismer@appliedbiometrics.com>
To: Phil Harris <phil@media-1.ml.uwcm.ac.uk>
Cc: <GBCGOLF@aol.com>; <tutor@python.org>
Sent: Thursday, March 11, 1999 10:12 AM
Subject: Re: [Tutor] Python Picture


>
>
>Phil Harris wrote:
>>
>> And now, the easy way to convert ico files to bitmaps.
>>
>> Open windows explorer, hilite the file to be converted, and rename it,
the
>> file is automaticaly converted by Windows.
>>
>> Easy when you know how eh!
>
>Did you ever test it? 3-[
>
>I did, and it doesn't work, at least not with my Win98 standard setup.
>
>I think you should stand in the corner, or I'm dumb.  <|:)
>
>Way out of the corner:
>Tell us what you installed to get the autoconversion,
>and please send me a converted py.ico file which
>is recognized by word :-)
>
>Well, I know there are some auto conversions available.
>Versions of WinZip know to convert a .zip file into
>a self extractor after you simply rename the file.
>But this is dependent of the availability of a converter,
>and I doubt this is installed by default for .ico files.
>
>renaming_.py_to_.exe_is_easier_than_freeze - ly y'rs chris.ico
>
>--
>Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
>Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
>Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
>10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
>PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
>     we're tired of banana software - shipped green, ripens at home
>
>_______________________________________________
>Tutor maillist  -  Tutor@python.org
>http://www.python.org/mailman/listinfo/tutor
>



From aa8vb@vislab.epa.gov  Thu Mar 11 15:48:58 1999
From: aa8vb@vislab.epa.gov (Randall Hopper)
Date: Thu, 11 Mar 1999 10:48:58 -0500
Subject: [Tutor] Tkinter
In-Reply-To: <01be6a6e$7ac796c0$0100007f@localhost>; from Jon Cosby on Tue, Mar 09, 1999 at 12:50:34PM -0800
References: <01be6a6e$7ac796c0$0100007f@localhost>
Message-ID: <19990311104858.A132573@vislab.epa.gov>

Jon Cosby:
 |   I need some help with Tkinter, and find the Pythonware tutorial to be
 |   lacking. I'd like create a button to call an application and dialog
 |   window for input, and present the results. Are there some good
 |   examples to look at to get me started?

I've been learning it lately too.  Here are some Tkinter links I've saved
off that might be useful:

http://hem1.passagen.se/eff/tkintro/Widgets.htm
http://starship.python.net/crew/hinsen/part6.html
http://www.python.org/topics/tkinter/doc.html
http://www.python.org/doc/life-preserver/index.html
http://www.pythonware.com/library.htm                 (Prob. the one you read)

Links on Tcl/Tk are useful too.  Once you know what you want to do in
Tcl/Tk, but aren't sure how that translates into Tkinter, consult the Life
Preserver reference manual (link #4).

There are a number of examples in the Python distribution pkg under
Python-1.5.1/Demo/tkinter (see http://www.python.org/download/).  You might
run them and look for GUIs with pieces that look like they might be useful,
and then browse the source and extract the widget or two that you want.

Randall


From tim_one@email.msn.com  Thu Mar 11 17:04:51 1999
From: tim_one@email.msn.com (Tim Peters)
Date: Thu, 11 Mar 1999 12:04:51 -0500
Subject: [Tutor] Python Picture
In-Reply-To: <36E79723.879FA05D@appliedbiometrics.com>
Message-ID: <000001be6be1$46c546a0$669e2299@tim>

[Phil Harris]
> And now, the easy way to convert ico files to bitmaps.
>
> Open windows explorer, hilite the file to be converted, and
> rename it, the file is automaticaly converted by Windows.
>
> Easy when you know how eh!

[Christian Tismer]
> Did you ever test it? 3-[
>
> I did, and it doesn't work, at least not with my Win98 standard setup.
>
> I think you should stand in the corner, or I'm dumb.  <|:)

Now, now, Phil may be an unwitting victim of Microsoft docs.  There's
actually a Knowledge Base article that makes a similar claim, in response to
a question like "how can I use a .bmp file as an icon?".  The answer says
you can rename .bmp -> .ico, and Windows "converts it".  In fact it does no
such thing, and indeed you can use a .bmp file as an icon without even
bothering to rename it.  It's trying to say that Windows converts it on the
fly when & if a .bmp is used as an icon; the disk file remains untouched.

even-easier-when-you-don't-have-to-ly y'rs  - tim




From priest@sfu.ca  Fri Mar 12 06:16:09 1999
From: priest@sfu.ca (David Priest)
Date: Thu, 11 Mar 1999 22:16:09 -0800
Subject: [Tutor] Singletons
In-Reply-To: <199903111706.MAA08701@python.org>
Message-ID: <4.1.19990311220422.00964360@mailserver.sfu.ca>

On the wxPython list, this tidbit was posted.  It has potential for really
simplifying complex GUI design (where one GUI element would influence the
appearance of another)... but I have a problem with it.

First, the pattern:

Singleton.py:
--snip---
def Singleton(parent):
    if __Singleton.instance:
        return __Singleton.instance
    __Singleton.instance = __Singleton(parent)
    return __Singleton.instance

class __Singleton:
    instance = None
    def __init__(self,parent):
         { place rest of class here }
--snip---

Now, the problem: GUI stuff tend to have a bunch of methods associated with
them.  How does one access them through the singleton?  If the class were
defining a window, for instance, then that class would have a "Close()" method.

Thus, the dropdown File menu entry for "Exit" might need to jump to code
that would do pre-exitting processing (saving files, etc), and then request
the application to shut down by calling the Close() method...

Main.py
--snip---
def Window():
	# as above
def __Window(window):
	def __init__:
		# set up window

	def Close(self):
		# shut down app
--snip---
Menu.py
--snip---
class FileMenu(menu):
	def __init__(self, etc):
		# set up the dropdown entries

         def Exit(self):
		# process the shutdown activities
		import Main
		Main.Window.Close()
--snip---

But the singleton pattern for Window() doesn't have a Close() method, of
course.  Error city.  Of course, *this* works, but is dead ugly....
--snip---
         def Exit(self):
		# process the shutdown activities
		import Main
		target = Main.Window()
		target.Close()
--snip---

So... here's this potentially *fantastic* resource -- something newbies
like me probably would take a year to think of trying -- that is rather
limited.

Of course, I've been discovering more and more that 
	"If something seems to be difficult to accomplish...
		...you're doing it wrong. Find the easy way."

Thanks for any hints, peeples!



From joe@strout.net  Fri Mar 12 17:10:44 1999
From: joe@strout.net (Joseph J. Strout)
Date: Fri, 12 Mar 1999 09:10:44 -0800
Subject: [Tutor] Singletons
In-Reply-To: <4.1.19990311220422.00964360@mailserver.sfu.ca>
References: <199903111706.MAA08701@python.org>
Message-ID: <v04020a06b30efad6362b@[198.202.70.213]>

At 10:16 PM -0800 03/11/99, David Priest wrote:

>def Window():
>	# as above
>def __Window(window):
>	def __init__:
>		# set up window
>
>	def Close(self):
>		# shut down app

>But the singleton pattern for Window() doesn't have a Close() method, of
>course.

Wait... if you've done something like

	myWindow = Window()

then myWindow is an object of class __Window (which is what the Window()
factory function returns, right?).  It has a Close() method.  What's the
problem?

Cheers,
-- Joe
,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'


From guido@CNRI.Reston.VA.US  Fri Mar 12 18:50:04 1999
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Fri, 12 Mar 1999 13:50:04 -0500
Subject: [Tutor] Re: Tutor digest, Vol 1 #5 - 12 msgs
In-Reply-To: Your message of "Thu, 11 Mar 1999 12:06:28 EST."
 <199903111706.MAA08700@python.org>
References: <199903111706.MAA08700@python.org>
Message-ID: <199903121850.NAA01649@eric.cnri.reston.va.us>

> From: Magnus L. Hetland <mlh@idt.ntnu.no>
> Subject: "Instant Hacking" - programming intro
> 
> I have made (or am making...) a small programming tutorial with Python
> as the example language. It is available from my Python page
> 
>   http://www.idi.ntnu.no/~mlh/python/
> 
> as "Instant Hacking". It is a work in progress - comments and
> suggestions are highly appreciated.

I've added a new category for this intro to the webpage listing
various Python introductions (http://www.python.org/doc/Intros.html).
If anybody else knows of any such intros, I would be delighted to add
them (if they use Python).

--Guido van Rossum (home page: http://www.python.org/~guido/)



From priest@sfu.ca  Sat Mar 13 17:32:12 1999
From: priest@sfu.ca (David Priest)
Date: Sat, 13 Mar 1999 09:32:12 -0800
Subject: [Tutor] Singletons
In-Reply-To: <199903131703.MAA18069@python.org>
Message-ID: <4.1.19990313093102.0095f100@mailserver.sfu.ca>

>>def Window():
>>	# as above
>>def __Window(window):
>>	def __init__:
>>		# set up window
>>
>>	def Close(self):
>>		# shut down app

Er, nevermind, everyone.  I just got generally clueless there for a bit.
Confused by previous sneaky code I'd been using that fooled me into
thinking I was doing something I wasn't...

<blush>

-- 
David Priest    w: 542-5208    e: priest@sfu.ca
Business Development Solutions:  "The Steps to Success"


From jlcos@accessone.com  Thu Mar 18 16:21:41 1999
From: jlcos@accessone.com (Jon Cosby)
Date: Thu, 18 Mar 1999 08:21:41 -0800
Subject: [Tutor] Question on lists
Message-ID: <01be715b$6806eec0$0100007f@localhost>

Hi - I'm trying to write a function that will return a list of prime factors
of a given number. For example, factor(36) would return [2,2,3,3]. What I
have so far is given below. Trouble is, each time it factors the quotient, a
is given as an empty list again. At this point, it's returning just the
first prime factor of the number. Is there any way to work around this?
Thanks in advance,

Jon Cosby

# Factor by trial division:
def factor(n):
     a = []                # Is there a better way to define a?
     k = floor(sqrt(n))
     for i in range(2, k+1):
          if n%i == 0:
             a.insert(len(a), i)
             factor(n/i)    # Factor quotient
             break
     return a




From joe@strout.net  Thu Mar 18 16:41:48 1999
From: joe@strout.net (Joseph J. Strout)
Date: Thu, 18 Mar 1999 08:41:48 -0800
Subject: [Tutor] Question on lists
In-Reply-To: <01be715b$6806eec0$0100007f@localhost>
Message-ID: <v04020a03b316dca9af89@[198.202.70.213]>

The basic problem is that you're saying:

>             a.insert(len(a), i)
>             factor(n/i)    # Factor quotient

i.e., you're saying "now factor the quotient", but you're not doing
anything with the result of this factorization!  You're imagining that it
will get appended to a, but how would Python know to do that unless you
tell it?

Also, I'd recommend using a.append to append an element to a, rather than
the insert construction used above.

Finally, there's a minor bug where you're factor() does not return a prime
number as its own factor, as it should.  The corrected function looks like
this:

# Factor by trial division:
def factor(n):
     a = []                # Is there a better way to define a?
     k = floor(sqrt(n))
     for i in range(2, k+1):
          if n%i == 0:
             a.append(i)   ### (append rather than insert)
             a.extend(factor(n/i))    ### add the factors of the quotient
             return a      ### don't break; just return
     # if not divisible by any of the above, then it must be prime
     return [n]


Cheers,
-- Joe
,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'


From pels@bio.uva.nl  Thu Mar 18 16:50:28 1999
From: pels@bio.uva.nl (bas pels)
Date: Thu, 18 Mar 1999 17:50:28 +0100
Subject: [Tutor] search path
Message-ID: <36F12ED4.A0EFAB0@bio.uva.nl>

a small question about search paths.

i have downloaded two so-called site-packages that both contain
x.pth files in their directories (so-called path configuration files).
from the reference manual  (p.57) i learnt that the site module uses 
these files to modify the sys.path list.

it seems to me that the path configuration files need to be in 
a specific directory (given by sys.prefix or sys.exec_prefix) to be
read. however, to put them there i need to be root.

is there a way to test the packages (and to make use of their path
configuration files) without travelling around as root?

thanks!
bas


From M.Faassen@vet.uu.nl  Thu Mar 18 16:47:59 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Thu, 18 Mar 1999 17:47:59 +0100
Subject: [Tutor] Question on lists
References: <01be715b$6806eec0$0100007f@localhost>
Message-ID: <36F12E3F.FD04AC0F@pop.vet.uu.nl>

Jon Cosby wrote:
[snip question]
 
> # Factor by trial division:
> def factor(n):
>      a = []                # Is there a better way to define a?
>      k = floor(sqrt(n))
>      for i in range(2, k+1):
>           if n%i == 0:
>              a.insert(len(a), i)
>              factor(n/i)    # Factor quotient
>              break
>      return a

Hullo,

This is a common phenomenon with recursive functions. In your function
you initialize a to a new empty list each time factor() gets called.
Instead, you need to pass the list that you are building along each time
you call the function. The usual Python trick for this is to use default
arguments to functions. This way you can pass the list on to each
recursive function, and the function still works as expected if you use
it with a single argument. 

Here's the improved function:

from math import floor, sqrt

def factor(n, a = []):        # if no second argument is passed, use the
empty list for a
    k = floor(sqrt(n))
    for i in range(2, k+1):
        if n%i == 0:
            a.append(i)       # more efficient and readable than
a.insert(len(a), i)
            factor(n/i, a)    # Factor quotient
            break
    return a

print factor(36) # test things

Note that there is still an algorithmic problem with your function; the
last quotient doesn't appear to be added to the list (k becomes smaller
than 2, namely 1, so the range command generates an empty list
(effectively nothing). The condition that ends the recursion appears to
be wrong (in your program it occurs whenever k <= 2). 

If this one of your first experiences with recursion, welcome to
recursion, that mystical powerful way to program (though it isn't too
fast in Python - go to functional programming languages such as lisp for
that). Do amazing things by just letting functions call themselves; it's
almost something for nothing! At least so it seemed to me at my first
brush with recursion.

Regards and good luck, 

Martijn


From da@ski.org  Thu Mar 18 21:23:56 1999
From: da@ski.org (David Ascher)
Date: Thu, 18 Mar 1999 13:23:56 -0800 (Pacific Standard Time)
Subject: [Tutor] Question on lists
In-Reply-To: <36F12E3F.FD04AC0F@pop.vet.uu.nl>
Message-ID: <Pine.WNT.4.04.9903181314260.261-100000@rigoletto.ski.org>

On Thu, 18 Mar 1999, Martijn Faassen wrote:

> Here's the improved function:
> 
> from math import floor, sqrt
> 
> def factor(n, a = []):        # if no second argument is passed, use the
>     k = floor(sqrt(n))
>     for i in range(2, k+1):
>         if n%i == 0:
>             a.append(i)       # more efficient and readable than a.insert(len(a), i)
>             factor(n/i, a)    # Factor quotient
>             break
>     return a
> 
> print factor(36) # test things

Martijn should know better than to use an empty list as a default argument
-- he was probably not awake when he wrote that.  Try calling factor(36) a
few times and look at the results:

>>> factor(36)
[2, 2, 3]
>>> factor(36)
[2, 2, 3, 2, 2, 3]
>>> factor(36)
[2, 2, 3, 2, 2, 3, 2, 2, 3]
>>> factor(36)
[2, 2, 3, 2, 2, 3, 2, 2, 3, 2, 2, 3]

That's because of the famous 'mutable default argument problem', discussed
in the FAQ Question 6.25 http://www.python.org/doc/FAQ.html#6.25.

The solution is to use None and do a test in the body of the function:

def factor(n, a = None):        
    if a is None: a = []
    k = floor(sqrt(n))
    for i in range(2, k+1):
        if n%i == 0:
            a.append(i)       
            factor(n/i, a)    
            break
    return a

>>> factor(36)
[2, 2, 3]
>>> factor(36)
[2, 2, 3]
>>> factor(36)
[2, 2, 3]
>>> factor(36)
[2, 2, 3]

Note that the code *still* doesn't work (it's missing a 3), but I'll leave
that one to others. =)

--david



From joe@strout.net  Thu Mar 18 21:42:35 1999
From: joe@strout.net (Joseph J. Strout)
Date: Thu, 18 Mar 1999 13:42:35 -0800
Subject: [Tutor] Question on lists
In-Reply-To: <Pine.WNT.4.04.9903181314260.261-100000@rigoletto.ski.org>
References: <36F12E3F.FD04AC0F@pop.vet.uu.nl>
Message-ID: <v04020a02b31723745261@[198.202.70.213]>

At 1:23 PM -0800 03/18/99, David Ascher wrote:

>That's because of the famous 'mutable default argument problem', discussed
>in the FAQ Question 6.25 http://www.python.org/doc/FAQ.html#6.25.
>
>The solution is to use None and do a test in the body of the function

A better solution still (IMHO) is to not pass the working content back to
the function at all, but instead to return it and append it locally, as in
the code I posted this morning.

,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'


From TomJenkins@zentuit.com  Thu Mar 18 22:04:04 1999
From: TomJenkins@zentuit.com (Tom Jenkins)
Date: Thu, 18 Mar 1999 17:04:04 -0500
Subject: [Tutor] Question on lists
In-Reply-To: <v04020a03b316dca9af89@[198.202.70.213]>
References: <01be715b$6806eec0$0100007f@localhost>
Message-ID: <199903182207.RAA14256@mail.digiweb.com>

> # Factor by trial division:
> def factor(n):
>      a = []                # Is there a better way to define a?
>      k = floor(sqrt(n))
>      for i in range(2, k+1):
>           if n%i == 0:
>              a.append(i)   ### (append rather than insert)
>              a.extend(factor(n/i))    ### add the factors of the quotient
>              return a      ### don't break; just return
>      # if not divisible by any of the above, then it must be prime
>      return [n]
> 
Hi Joe,
I get an AttributeError on extend.  Is this a 1.5.2 enhancement?  Or is 
there a compile time option (I grabbed the binaries for both Win & Linux).
Thanks,

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Tom Jenkins                    DevIS (http://www.devis.com)
Y2K problem? The Mayans didn't have a millennium-2K problem! 
Eric S. Raymond at IPC7, on learning that the Mayan calendar 
takes 28 octillion years to wrap around


From joe@strout.net  Thu Mar 18 22:17:31 1999
From: joe@strout.net (Joseph J. Strout)
Date: Thu, 18 Mar 1999 14:17:31 -0800
Subject: [Tutor] Question on lists
In-Reply-To: <199903182207.RAA14256@mail.digiweb.com>
References: <v04020a03b316dca9af89@[198.202.70.213]>
 <01be715b$6806eec0$0100007f@localhost>
Message-ID: <v04020a03b3172bb24252@[198.202.70.213]>

At 2:04 PM -0800 03/18/99, Tom Jenkins wrote:

>>              a.extend(factor(n/i))    ### add the factors of the quotient

>I get an AttributeError on extend.  Is this a 1.5.2 enhancement?  Or is
>there a compile time option (I grabbed the binaries for both Win & Linux).

Whoops, must be a 1.5.2 thing.  No wonder I hadn't heard of it before last
week!  =)

Barring that, then just do:

		a = a + factor(n/i)

which is pretty much equivalent (unless somebody else has a reference to a...).

Cheers,
-- Joe
,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'


From tim_one@email.msn.com  Fri Mar 19 09:30:50 1999
From: tim_one@email.msn.com (Tim Peters)
Date: Fri, 19 Mar 1999 04:30:50 -0500
Subject: [Tutor] Question on lists
In-Reply-To: <01be715b$6806eec0$0100007f@localhost>
Message-ID: <000501be71eb$2d75ca20$409e2299@tim>

The questions about recursion and ways to fiddle lists were covered well
already, so I'd just like to encourage you to think about other ways to
solve the problem.  Attached is a very similar algorithm that doesn't use
recursion.  Which is faster?  Which is clearer?  Which gives the right
answer <wink>?

not-rhetorical-questions-ly y'rs  - tim

def factor(n):
    a = []
    d = 2
    while d*d <= n:
        while n % d == 0:
            a.append(d)
            n = n / d
        d = d + 1
    if n > 1 or not a:
        a.append(n)
    return a




From M.Faassen@vet.uu.nl  Mon Mar 22 09:23:39 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Mon, 22 Mar 1999 10:23:39 +0100
Subject: [Tutor] Question on lists
References: <Pine.WNT.4.04.9903181314260.261-100000@rigoletto.ski.org>
Message-ID: <36F60C1B.2F90E1C8@pop.vet.uu.nl>

David Ascher wrote:
 
> Martijn should know better than to use an empty list as a default argument
> -- he was probably not awake when he wrote that. 

I should know better; my excuse is that the bug just hasn't bitten me
before; I was well aware of problems, but I keep mixing up *what*
problems. I actually *did* think about doing the None thing but left it
out for 'clarity'. Silly me.

Thanks for the 'not awake' excuse, by the way. ;)

> Try calling factor(36) a
> few times and look at the results:

Okay, now that I've actually been bitten by this bug I'll better my
life. :) 
 
Regards,

Martijn


From alan.gauld@bt.com  Thu Mar 25 14:34:56 1999
From: alan.gauld@bt.com (alan.gauld@bt.com)
Date: Thu, 25 Mar 1999 14:34:56 -0000
Subject: [Tutor] __init__ problem
Message-ID: <5104D4DBC598D211B5FE0000F8FE7EB24E08E0@mbtlipnt02.btlabs.bt.co.uk>

Given:

class Transaction:
    def __init__(self):
    	self.total = self.paid = self.change = 0
    	self.GST = 0.07
    	self.items = []

class RentalTransaction(Transaction):
    def __init__(self):
    	Transaction.__init__(self)
    	pass

why do I get:

>>> r = RentalTransaction()
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
  File "C:\Program Files\Python\Projects\transact.py", line 38, in __init__
    Transaction.__init__(self)
TypeError: unbound method must be called with class instance 1st argument
>>> 

Alan G.


From M.Faassen@vet.uu.nl  Thu Mar 25 15:13:32 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Thu, 25 Mar 1999 16:13:32 +0100
Subject: [Tutor] __init__ problem
References: <5104D4DBC598D211B5FE0000F8FE7EB24E08E0@mbtlipnt02.btlabs.bt.co.uk>
Message-ID: <36FA529C.D334A0F6@pop.vet.uu.nl>

alan.gauld@bt.com wrote:
> 
> Given:
> 
> class Transaction:
>     def __init__(self):
>         self.total = self.paid = self.change = 0
>         self.GST = 0.07
>         self.items = []
> 
> class RentalTransaction(Transaction):
>     def __init__(self):
>         Transaction.__init__(self)
>         pass
> 
> why do I get:
> 
> >>> r = RentalTransaction()
> Traceback (innermost last):
>   File "<interactive input>", line 1, in ?
>   File "C:\Program Files\Python\Projects\transact.py", line 38, in __init__
>     Transaction.__init__(self)
> TypeError: unbound method must be called with class instance 1st argument
> >>>

Hm, this works for me. Are you sure you are re-importing the module into
Python? Perhaps you're having some old module in memory that's
disrupting stuff. Try quitting interactive mode and starting again. I
myself don't use interactive mode a lot. To test I just added r =
RentalTransaction() to the .py file with the source, and hit C-c C-c in
Emacs to execute the buffer. :)

Regards,

Martijn


From joe@strout.net  Thu Mar 25 16:12:32 1999
From: joe@strout.net (Joseph J. Strout)
Date: Thu, 25 Mar 1999 08:12:32 -0800
Subject: [Tutor] __init__ problem
In-Reply-To: <5104D4DBC598D211B5FE0000F8FE7EB24E08E0@mbtlipnt02.btlabs.bt.co.uk>
Message-ID: <v04020a02b32010999957@[198.202.70.213]>

At 6:34 AM -0800 03/25/99, alan.gauld@bt.com wrote:

>class RentalTransaction(Transaction):
>    def __init__(self):
>    	Transaction.__init__(self)
>    	pass
>
>why do I get:
>
>>>> r = RentalTransaction()
>Traceback (innermost last):
>  File "<interactive input>", line 1, in ?
>  File "C:\Program Files\Python\Projects\transact.py", line 38, in __init__
>    Transaction.__init__(self)
>TypeError: unbound method must be called with class instance 1st argument
>>>>

Beats me.  I copied and pasted your code, and it works just fine for me.
The code is correct (though the "pass" on the second line of
RentalTransaction.
__init__ is superfluous).  Looks like a bug in your Python, perhaps?

Cheers,
-- Joe
,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'


From cwebster@math.tamu.edu  Thu Mar 25 16:38:02 1999
From: cwebster@math.tamu.edu (Corran Webster)
Date: Thu, 25 Mar 1999 10:38:02 -0600 (CST)
Subject: [Tutor] __init__ problem
In-Reply-To: <5104D4DBC598D211B5FE0000F8FE7EB24E08E0@mbtlipnt02.btlabs.bt.co.uk>
Message-ID: <199903251638.KAA13573@radon.math.tamu.edu>

On 25 Mar, alan.gauld@bt.com wrote:
> Given:
> 
> class Transaction:
>     def __init__(self):
>     	self.total = self.paid = self.change = 0
>     	self.GST = 0.07
>     	self.items = []
> 
> class RentalTransaction(Transaction):
>     def __init__(self):
>     	Transaction.__init__(self)
>     	pass
> 
> why do I get:
> 
>>>> r = RentalTransaction()
> Traceback (innermost last):
>   File "<interactive input>", line 1, in ?
>   File "C:\Program Files\Python\Projects\transact.py", line 38, in __init__
>     Transaction.__init__(self)
> TypeError: unbound method must be called with class instance 1st argument
>>>> 

I copied and pasted the example and it works fine for me (Python 1.5.1
on Solaris), but I notice that you are indenting using both tabs and
spaces.  While the combination of tabs and spaces that appreared in you
message appears to be consistent (each singly indented line has 4
spaces, each doubly indented line has 4 spaces followed by one tab), it
might be worthwhile checking that the original version doesn't have an
additional tab somewhere which is causing a conflict.

In general it is a very bad idea to indent using spaces and tabs, use
one or the other, but not both together.  Unfortunately some editors can
be bad about automatically inserting them.  I'd recommend going through
and replacing all your tabs by spaces to ensure correct indentation,
and then seeing if it works.

Regards,
Corran




From jlcos@accessone.com  Thu Mar 25 20:35:14 1999
From: jlcos@accessone.com (Jon Cosby)
Date: Thu, 25 Mar 1999 12:35:14 -0800
Subject: [Tutor] Writing to output file
Message-ID: <01be76fe$fca9a6a0$0100007f@localhost>

This should be an easy one, but I'm not finding it: How do you print to an
output file? I'm trying to get the results of search.py below on a text
file. Nothing I've tried seems to work.
Maybe somebody can tell me why it's so slow, too; it took it 15 minutes to
search a 115 MB archive.

Jon Cosby

-----------------------------------Start
search.py--------------------------------------
# Search.py
# Counts (case-insensitive) instances of string in a given directory and
it's sub-directories
# To-do: Include file names in the search; search multiple strings

import re, sys, os

def searchtext(filename, text):
     line = "initialized"
     infile = open(filename, 'r')
     outfile = open('c:\\data\\results.txt', 'w')
     a = []
     while line != "":
          line = infile.readline()
          b = re.compile(text, re.I).findall(line)
          if len(b) > 0:
               a.extend(b)
     if len(a) > 0:
         print filename, text, ':', len(a)     # I want to write this to
'results.txt'
     else:                                                # Seems like a
simple problem, but the
         return 0                                     # documents only give
instructions
 infile.close()                                     # for writing a string.
 outfile.close()

def getFile(dir, text):
     dl = os.listdir(dir)
     for i in range(len(dl)):
        dl[i] = dir + '\\' + dl[i]
        if os.path.isfile(dl[i]):
            searchtext(dl[i], text)
        else:
            getFile(dl[i], text)

if __name__ == '__main__':
     getFile(sys.argv[1], sys.argv[2])

------------------------------------------------------End
search.py-----------------------------------------------------



From M.Faassen@vet.uu.nl  Thu Mar 25 20:56:22 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Thu, 25 Mar 1999 21:56:22 +0100
Subject: [Tutor] Writing to output file
References: <01be76fe$fca9a6a0$0100007f@localhost>
Message-ID: <36FAA2F6.1EA2801@pop.vet.uu.nl>

Hiya,

You can write strings to a textfile, of course, and first translate
other types to strings, using str() or using the % operator. "%s" %
a_value, for instance.

Another way is to redirect sys.stdout to a file object. That makes all
your print statements print to the file instead of to the console:

# import sys to get at stdout (standard output)
import sys

# open a file for writing
f = open("myfile.txt", "w")
# okay, our standard output is now that file
sys.stdout = f

# this prints to the file
print "Foo", 6, "bar"

I hope this helps,

Regards,

Martijn


From joe@strout.net  Thu Mar 25 21:00:47 1999
From: joe@strout.net (Joseph J. Strout)
Date: Thu, 25 Mar 1999 13:00:47 -0800
Subject: [Tutor] Writing to output file
In-Reply-To: <01be76fe$fca9a6a0$0100007f@localhost>
Message-ID: <v04020a01b320545b865d@[198.202.70.213]>

You just set sys.stdout to your file...

import sys

...
oldstdout = sys.stdout
sys.stdout = open("results.txt", 'w')
print "here's some data...."
...
sys.stdout = oldstdout


Cheers,
-- Joe
,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'


From cwebster@math.tamu.edu  Thu Mar 25 22:55:04 1999
From: cwebster@math.tamu.edu (Corran Webster)
Date: Thu, 25 Mar 1999 16:55:04 -0600 (CST)
Subject: [Tutor] Writing to output file
In-Reply-To: <01be76fe$fca9a6a0$0100007f@localhost>
Message-ID: <199903252255.QAA23618@radon.math.tamu.edu>

On 25 Mar, Jon Cosby wrote:
> This should be an easy one, but I'm not finding it: How do you print to an
> output file? I'm trying to get the results of search.py below on a text
> file. Nothing I've tried seems to work.

To write to a file, you want to use the write method of the file
object.  Looking at your code, you want something like:

    outfile.write("%s:%d" % (text, len(a)))

or

    outfile.write(text + ":" + `len(a)`)

or even

    outfile.write(text + ":" + str(len(a)))

or, as has been mentioned by others, you can redirect standard output
to your file.

> Maybe somebody can tell me why it's so slow, too; it took it 15 minutes to
> search a 115 MB archive.

I suspect a lot of the slowness comes from the fact that you are
compiling your regular expression every time you go through the loop. 
Also I am a little unclear about why you need to keep a copy of the
matches when all you seem to be interested in is the number of matches.
Both these could be factors, as could be the simple fact that 115 MB is
a lot of data, and Python is slower than C.

For other issues, I think you want to open your results file in the
getfile if you are going to be processing many different files - if you
open and close the file within the searchtext function, you will
overwrite the results file each time you search.  If you don't
need the full power of regular expressions you may be able to
get away with using string.count(). Finally, the os.path.walk function
will improve your getFile function - it does much the same thing, but is
more robust and will work on any platform without modification.

(Warning! The following code is untested - I only have 1.5.1 here,
findall requires 1.5.2.)

import os, re, sys

def searchfile(text, filename):
  n = 0
  pat = re.compile(text, re.I)
  try:
    infile = open(filename, "r")
  except IOError:
    # can't open the file or something similar
    print filename, ": Cannot open"
  else:
    line = infile.readline()
    while line:
      n = n + len(pat.findall(line))
      line = infile.readline()
    print filename, ":", n
    infile.close()

def searchdir(text, dir, names):
  for name in names:
    fullname = os.path.join(dir, name)
    if os.path.isfile(fullname):
      searchfile(text, fullname)

def searchtree(text, dir):
  os.path.walk(dir, searchdir, text)

if __name__ == "__main__":
  outfile = open('c:\\data\\results.txt', 'w')
  oldstdout = sys.stdout
  sys.stdout = outfile
  
  searchtree(sys.argv[1], sys.argv[2])
  
  sys.stdout = oldstdout
  outfile.close()





From jlcos@accessone.com  Fri Mar 26 20:36:21 1999
From: jlcos@accessone.com (Jon Cosby)
Date: Fri, 26 Mar 1999 12:36:21 -0800
Subject: [Tutor] Listing web contents
Message-ID: <01be77c8$4f2d83a0$0100007f@localhost>

Hi - Is there any way of listing the directory contents of a URL address?
Something like

dir = urllib.urlopen(url)
os.listdir(dir)

Thanks,

Jon Cosby



From joe@strout.net  Fri Mar 26 20:50:12 1999
From: joe@strout.net (Joseph J. Strout)
Date: Fri, 26 Mar 1999 12:50:12 -0800
Subject: [Tutor] Listing web contents
In-Reply-To: <01be77c8$4f2d83a0$0100007f@localhost>
Message-ID: <v04020a12b321a32de179@[198.202.70.213]>

At 12:36 PM -0800 03/26/99, Jon Cosby wrote:

>Hi - Is there any way of listing the directory contents of a URL address?
>Something like
>
>dir = urllib.urlopen(url)
>os.listdir(dir)

No.  A URL address does not refer to a file.  It refers to a document,
which may (if the server so chooses) represent a listing of files, but it's
still a document.  Asking "how to list the directory contents of a URL
address" doesn't make sense.  Your example would be equivalent to:

f = open("somefile.txt")
os.listdir(f)

Cheers,
-- Joe
,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'


From joe@strout.net  Fri Mar 26 21:06:29 1999
From: joe@strout.net (Joseph J. Strout)
Date: Fri, 26 Mar 1999 13:06:29 -0800
Subject: [Tutor] Listing web contents
Message-ID: <v04020a13b321a713cc12@[198.202.70.213]>

...I should add that URL refer to documents when the protocol is http.  If
the protocol is something else, like ftp for example, then a URL could
refer to a directory.  I didn't think of that earlier.  But I'm still
pretty sure you can't use urllib to list the contents of such a directory;
you'd have to use the ftp module instead.

Cheers,
-- Joe
,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'


From guido@CNRI.Reston.VA.US  Sat Mar 27 13:11:42 1999
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Sat, 27 Mar 1999 08:11:42 -0500
Subject: [Tutor] Re: Listing web contents
In-Reply-To: Your message of "Sat, 27 Mar 1999 01:06:31 EST."
 <199903270606.BAA23528@python.org>
References: <199903270606.BAA23528@python.org>
Message-ID: <199903271311.IAA28831@eric.cnri.reston.va.us>

> Hi - Is there any way of listing the directory contents of a URL address?
> Something like
> 
> dir = urllib.urlopen(url)
> os.listdir(dir)

I'm assuming the URL points to an HTML document, and what you really
want is a listing of URLs that the given URL refers to.

In this case, you can cook something up using Python's HTML parsing
library module (htmllib).

I'm guessing that what you area really looking for is writing an
automated tool that browses a tree of related pages on the web.
In this case, please have a look at webchecker in the Python source
distribution, Tools/webchecker/.

PS.  To the tutors.  I see no significant difference between the tutor
list and the help list.  Perhaps tutor should be merged back into
help?

--Guido van Rossum (home page: http://www.python.org/~guido/)



From Treed@CAM.ORG  Sat Mar 27 13:19:27 1999
From: Treed@CAM.ORG (Tony Reed)
Date: Sat, 27 Mar 1999 08:19:27 -0500
Subject: [Tutor] Listing web contents
In-Reply-To: <v04020a13b321a713cc12@[198.202.70.213]>
Message-ID: <v03130302b3228a123374@[205.151.118.3]>

On 26/3/99, Joseph J. Strout wrote:

:...I should add that URL refer to documents when the protocol is http.  If
:the protocol is something else, like ftp for example, then a URL could
:refer to a directory.  I didn't think of that earlier.  But I'm still
:pretty sure you can't use urllib to list the contents of such a directory;
:you'd have to use the ftp module instead.


What a URL returns is dependant on the protocol used and to a certain extent
the server.  So <http://www.some.com/somedir/> would tell the Apache server to look 
in the directory somedir for an document called index.html, and to display it.  If no
index.html is found, then Apace will return a listing of the directory.

Of course, savvy web designers put an index.html in _every_ directory, to foil the nosy. . .


-- 
Tony Reed
<mailto:Treed@CAM.ORG>




From rbb@nebiometrics.com  Sat Mar 27 13:21:53 1999
From: rbb@nebiometrics.com (Robert Burrows)
Date: Sat, 27 Mar 1999 08:21:53 -0500 (EST)
Subject: [Tutor] using command line arguments
Message-ID: <Pine.LNX.4.02.9903270820090.6943-100000@localhost.localdomain>

Hello,

How can I use a command line argument in range()? I think I need something
like C's atoi().

TIA,

Robert Burrows
rbb@nebiometrics.com




From tismer@appliedbiometrics.com  Sat Mar 27 15:06:52 1999
From: tismer@appliedbiometrics.com (Christian Tismer)
Date: Sat, 27 Mar 1999 16:06:52 +0100
Subject: [Tutor] using command line arguments
References: <Pine.LNX.4.02.9903270820090.6943-100000@localhost.localdomain>
Message-ID: <36FCF40C.7EEBCCF8@appliedbiometrics.com>


Robert Burrows wrote:
> 
> Hello,
> 
> How can I use a command line argument in range()? I think I need something
> like C's atoi().

Right, a command line argument always comes as a string.
The sys.argv list is a list of string which you need to
parse.

The string module has exactly that function which you mention:
>>> import string
>>> s="123"
>>> string.atoi(s)
123
>>> 

Friends are string.atof for floats and string.atol for longs.
string.atoi provides you with an extra parameter 'base' which
defaults to 10, but here you can use 16 for instance if you
want atoi to parse hexadecimal numbers.

If you don't need an extra base parameter, it is easier to
just use the standard functions int and float, which don't
need to be imported.
>>> int("123")
123
>>> 

There is another issue if you are handling command line
parameters: Your program should recover gracefully
if the user did not specify a parameter at all, or if it was
no string. The easiest way to do this is to catch an exception.
Here the quick example:
>>> try:
... 	int("123c")
... except ValueError:
... 	print "this was not a number"
... 	raise SystemExit, 1
... 	
this was not a number
Traceback (innermost last):
  File "<interactive input>", line 5, in ?
SystemExit: 1
>>> 

Now, after we have figured out the details, we can write
a minimum comand line handler for your case.
The following sample program prints a number range to
your console, or dies with an error message.

#from here
def int_tuple_from_cmdline():
      """return exactly two integers form sys.argv
         or die with an error message
      """
      import sys
      args = sys.argv[1:] # drop first entry (progpath)
      if len(args) != 2:
          raise SystemExit("expected two integer parameters")
      for i in range(len(args)):
          try:
             args[i] = int(args[i])
          except ValueError:
             raise SystemExit("Parameter %d is no integer:%s" %(i+1,
args[i]))
      return tuple(args)

start, stop = int_tuple_from_cmdline()
print range(start, stop)
#to here

Now, here is my session log:

D:\tmp>python log.py 2 11
[2, 3, 4, 5, 6, 7, 8, 9, 10]

D:\tmp>python log.py 2
expected two integer parameters

D:\tmp>python log.py 2 notanumber
Parameter 2 is no integer:notanumber

hope this helps - ciao - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home


From tismer@appliedbiometrics.com  Sat Mar 27 15:17:14 1999
From: tismer@appliedbiometrics.com (Christian Tismer)
Date: Sat, 27 Mar 1999 16:17:14 +0100
Subject: [Tutor] Purpose of this list (was: Listing web contents)
References: <199903270606.BAA23528@python.org> <199903271311.IAA28831@eric.cnri.reston.va.us>
Message-ID: <36FCF67A.91B1ADBE@appliedbiometrics.com>

[contents dropped]
Guido:
> PS.  To the tutors.  I see no significant difference between the tutor
> list and the help list.  Perhaps tutor should be merged back into
> help?

I don't think so.
Python-help is anonymous. Its purpose is to help people 
with advice anonymously. After a helper has taken his
hand, the rest of the conversation will usually disappear.

Tutor has a slightly different purpose. Besides helping 
people, we also try to leave the conversations as a useful
archive, which could serve as a basis for more. This could
finally be material for some cookbook. (Python a'la carte).
I don't just see it as help, but as a collection.

For me this makes very much sense. The tutors are all suffering
from being too experienced to imagine beginners problems. 
Offering a list where everybody is invited to ask any question 
brings things to mind which have vanished for a long time.

Example: I would never think of writing about how to
parse two integers from the command line if the question
was not here. It encourages us to write some pieces of prose,
instead of these short "ack - use int()" answers.
I really do think about a book.

cheers - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home


From tismer@appliedbiometrics.com  Sat Mar 27 15:37:08 1999
From: tismer@appliedbiometrics.com (Christian Tismer)
Date: Sat, 27 Mar 1999 16:37:08 +0100
Subject: [Tutor] search path
References: <36F12ED4.A0EFAB0@bio.uva.nl>
Message-ID: <36FCFB24.39442E4B@appliedbiometrics.com>


bas pels wrote:
> 
> a small question about search paths.
> 
> i have downloaded two so-called site-packages that both contain
> x.pth files in their directories (so-called path configuration files).
> from the reference manual  (p.57) i learnt that the site module uses
> these files to modify the sys.path list.
> 
> it seems to me that the path configuration files need to be in
> a specific directory (given by sys.prefix or sys.exec_prefix) to be
> read. however, to put them there i need to be root.
> 
> is there a way to test the packages (and to make use of their path
> configuration files) without travelling around as root?

Yes. I believe the easiest way is to manually adjust the 
startup a little and test the packages.
If you have a look into site.py, you will see that function
addsitedir(path) does what you want.
I would start my testing script this way:

#from here
from site import addsitedir
addsitedir('/home/pels/python/newstuff')
del addsitedir
# assuming a package "superpackage" in newstuff
from superpackage import tester
tester()
#to here

Makes sense? ciao - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home


From ajs@ix.netcom.com  Fri Mar 26 23:17:02 1999
From: ajs@ix.netcom.com (Art Siegel)
Date: Fri, 26 Mar 1999 18:17:02 -0500
Subject: [Tutor] Re: super classes
Message-ID: <000201be7867$a6071840$2e82f3d0@seigel.eico.com>

I have come across considerable discussion about "super" classing on the
Python newsgroup.

I need more of a what is than a how to.

What is the definition, basic function, and significance of a super class.

Help - as always - is appreciated






From joe@strout.net  Sat Mar 27 16:02:16 1999
From: joe@strout.net (Joseph J. Strout)
Date: Sat, 27 Mar 1999 08:02:16 -0800
Subject: [Tutor] Re: super classes
In-Reply-To: <000201be7867$a6071840$2e82f3d0@seigel.eico.com>
Message-ID: <l03102801b322b0f124f4@[204.210.62.164]>

A superclass is the parent of some other class, i.e., the class from which
it is derived.  When you write:

class Shape:
	(...stuff all Shapes can do goes here...)

class Circle(Shape):
	(...stuff specific to Circle shapes goes here...)


then "Shape" is the superclass of Circle, and Circle is the subclass of
Shape.  Subclass/superclass is just a relationship, like child/parent.

Another terminology which is often used is base class (Shape) and derived
class (Circle).

Cheers,
-- Joe

,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'




From ajs@ix.netcom.com  Sat Mar 27 17:52:19 1999
From: ajs@ix.netcom.com (Art Siegel)
Date: Sat, 27 Mar 1999 12:52:19 -0500
Subject: [Tutor] Re: super classes
Message-ID: <000801be787a$90647b00$2e82f3d0@seigel.eico.com>

-----Original Message-----
From: Joseph J. Strout <joe@strout.net>
To: Art Siegel <ajs@ix.netcom.com>; Python Tutor <tutor@python.org>
Date: Saturday, March 27, 1999 11:03 AM
Subject: Re: [Tutor] Re: super classes


>A superclass is the parent of some other class, i.e., the class from which
>it is derived.

Now that I understand the terminology, a few more questions:

Java has a "super" function, I believe, which I assume allows one to
directly access methods of the parent class from inside the child class.

Under what circumstances is it useful? Aren't, by definition, the parent's
method already at the disposal of the child?

What is the Python equivalent to the java super call?

This is all coming up as I try to understand some java code and port it to
Python.







From tismer@appliedbiometrics.com  Sat Mar 27 18:45:02 1999
From: tismer@appliedbiometrics.com (Christian Tismer)
Date: Sat, 27 Mar 1999 19:45:02 +0100
Subject: [Tutor] Re: super classes
References: <000801be787a$90647b00$2e82f3d0@seigel.eico.com>
Message-ID: <36FD272E.599E400@appliedbiometrics.com>


Art Siegel wrote:
...
> Now that I understand the terminology, a few more questions:
> 
> Java has a "super" function, I believe, which I assume allows one to
> directly access methods of the parent class from inside the child class.
> 
> Under what circumstances is it useful? Aren't, by definition, the parent's
> method already at the disposal of the child?

Usually yes. But sometimes your subclass or your instance defines
its own version of an attribute, and the parent's is hidden.
In Java, super allows you to access overridden methods.
I think, this is also used if one wants to use the inherited
function in the implementation of the new function. Something
for "do the old thing, but this also".

> What is the Python equivalent to the java super call?

There is no direct equivalent, but something alike.
If you have a derived class which redefines a method
of its superclass and you need to call that, you have
several choices:

If you know the name of the superclass, you can simply refer to
the class and use its method.

Here an example which might clarify this.

#from here
class classa:
	def say(self, text):
	  print "classa says '%s'" % text

class classb(classa):
	def say(self, text):
	  print "but classb says '%s'" % text

inst = classb()
#to here

Now, inst can say hello:

>>> inst.say("hello")
but classb says 'hello'
>>> 

What happens here is that the method "say" is looked up in
inst's __dict__, where it is not found, so it is looked
up in its class's __dict__ where it is found.
The unbound method "say" of classb is then bound to inst
(this means providing inst as parameter self) and called with
the additional arguments.
You can get the same result by calling th unbound method
by yourself:

>>> classb.say(inst, "hello")
but classb says 'hello'
>>>

The same way, we can call the superclass's method 

>>> classa.say(inst, "hello")
classa says 'hello'
>>> 

This is allowed if inst is an instance of that class or
any of its subclasses.

Now, what if you want to access a superclass method without
spelling its name?

>>> inst.__class__.__bases__[0].say(inst, "hello")
classa says 'hello'
>>> 

inst always has an attribute __class__ which is its class.
The class has an attribute __bases__ which is a tuple
with all the classes which appeared in the class statement.
In this case, there is just one entry, classa. In general,
you must expect that a class is a subclass of more than one
since Python has multiple inheritance. Then you need to know
the class' index in the __bases__ tuple to call the right
method.

A more common problem is to access a class variable instead
of the instance's. You know, every instance can redefine
any attribute, wether the class provides it or not.
I don't think it should be a recommended practice, but
a situation might appear where a user is allowed to
put arbitrary attributes into an instance, and you must
be sure to use always the class attribute

Assume the following situation:

>>> class circle:
...     defaultperimeter = 100
...     maximumperimeter = 100
...     def draw(self, x, y, perimeter):
...         if perimeter > circle.maximumperimeter:
...             perimeter = circle.defaultperimeter
...         print "drawing at (%d,%d) p=%d" % (x, y, perimeter)
... 	
>>> c=circle()
>>> c.draw(10,10,200)
drawing at (10,10) p=100
>>> c.defaultperimeter=1000 # ha, no chance!
>>> c.draw(10,10,200)
drawing at (10,10) p=100
>>> 

The instance cannot change the defaultperimeter.

>>> c.defaultperimeter
1000
>>> 

Observe, that I used the class name "circle" explicitly.
If I had referred to self.__class__, then a user could
overwrite the defaultperimeter again, like this:

>>> class circle:
...     defaultperimeter = 100
...     maximumperimeter = 100
...     def draw(self, x, y, perimeter):
...         if perimeter > self.__class__.maximumperimeter:
...             perimeter = self.__class__.defaultperimeter
...         print "drawing at (%d,%d) p=%d" % (x, y, perimeter)
... 
>>> class othercircle(circle):
... 	  defaultperimeter = 1000
... 	
>>> c=othercircle()
>>> c.draw(10, 20, 1000)
drawing at (10,20) p=1000
>>> c.defaultperimeter = 200
>>> c.draw(10, 20, 1000)
drawing at (10,20) p=1000
>>> 

As you can see, self.__class__ always referres to the actual
class of the object, no matter that draw was defined in
a different class.
Here we overwrote a class attribute by subclassing, where
the extra attribute of the instance was ignored.

> This is all coming up as I try to understand some java code and port it to
> Python.

What are you porting, btw?

ciao - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home


From ajs@ix.netcom.com  Sat Mar 27 19:49:25 1999
From: ajs@ix.netcom.com (Art Siegel)
Date: Sat, 27 Mar 1999 14:49:25 -0500
Subject: [Tutor] Re: super classes
Message-ID: <000601be788a$ee0e7f20$2e82f3d0@seigel.eico.com>

>What are you porting, btw?
>
Thanks for response.  I haven't absorbed it yet but I will.

Your sample code is on point because I am doing graphic stuff - mostly with
David's PyOpenGL.

I have also taken a few shots at using OpenGL through Java using JPython.
The one Java OpenGL implementation that I got at (with David's help) was
Magician.  Magician was commercial, its recent versions available for
download were crippled - and, even if I wanted to license it, it  in fact
has been abandoned by its developers.

So, what I am trying to port to JPython now are demos of GL4Java - a GNU
license product and what looks like a good implementation of OpenGl for Java


From ivnowa@hvision.nl  Sat Mar 27 22:27:43 1999
From: ivnowa@hvision.nl (Hans Nowak)
Date: Sat, 27 Mar 1999 23:27:43 +0100
Subject: [Tutor] Python Snippets Site
Message-ID: <199903272221.XAA10583@axil.hvision.nl>

Howdy y'all,

This tutor forum looks like a good place to announce my Python Snippets site. 
(In fact, it's been there for a while, but I've been reluctant to show it to 
the world.)

In this case, "snippets" are small, *working* pieces of Python code. 
"Working" means here that you can take a snippet, feed it to Python, and it 
works right out of the box, without any implicit assumptions ("it's obvious 
that this module should have been imported" etc). People who have a certain 
Python question, can go to this site and see if the solution is there. Of 
course, anybody who wants learn something new can browse it.

Anyway, that's the goal. So far not too much snippets are in the repository 
yet, and those who are, might need a double check. A lot of new ones are 
waiting on my hard disk, but before I spend much energy to working on this 
site, I want to know if it will be useful to a lot of people.

Here's what I offer:  ;^)

http://www.hvision.nl/~ivnowa/snippets/

(It's still under construction, and as I said, there aren't many snippets 
yet, but before I continue to work on it, I need to know if it's worth 
working on.)

Here's what I need:

1) Feedback. It's cool making such a site, but if I don't get any reactions, 
I won't know if things are good or bad, useful or crockish, etc.

2) More snippets. Lots more! The more, the merrier. A site with lots of 
snippets is of course more likely to have the solution to one's problem. I 
feel that picking snippets is not something one person should do. If your 
question is satisfactorily answered by a Python guru, and s/he has provided 
you with some nice code, I'd like to hear from it. Similarly, if you've just 
developed and posted some great code, I'd appreciate it if you could cc me 
the file. Sure enough, I can find it in the newsgroup myself -- but if anyone 
will be so friendly to forward his code, this would speed up things a lot. 
Because to be honest, I don't have much time to wade through myriads of files 
looking for that one gem of Python code.

The email address is hey_psst@usa.net. (PSST stands for Python Snippet 
Support Team. ;^) Please do not use my other email addresses for this 
purpose. Depending on your reactions and support, this site will live... or 
die.

Veel liefs,

+  Hans Nowak  (Zephyr Falcon)
+  Homepage (under construction): http://www.cuci.nl/~hnowak/
+  You call me a masterless man. You are wrong. I am my own master.
+  May Grandma Moses bake your heavy burden!


From skip@mojam.com (Skip Montanaro)  Sun Mar 28 14:04:14 1999
From: skip@mojam.com (Skip Montanaro) (skip@mojam.com (Skip Montanaro))
Date: Sun, 28 Mar 1999 09:04:14 -0500 (EST)
Subject: [Tutor] Re: Listing web contents
In-Reply-To: <199903271311.IAA28831@eric.cnri.reston.va.us>
References: <199903270606.BAA23528@python.org>
 <199903271311.IAA28831@eric.cnri.reston.va.us>
Message-ID: <14078.13833.155285.406265@toshiba-54-180.nycap.rr.com>

    Guido> PS.  To the tutors.  I see no significant difference between the
    Guido> tutor list and the help list.  Perhaps tutor should be merged
    Guido> back into help?

Well, recently the python-help list has turned into more-or-less a single
question list, which boils down to someone asking, "how can I use Python to
break into other computers?" to which someone replies, "Get a life!  Read
Eric Raymond's 'How to Become a Hacker'".  Thus far I haven't seen any of
that on the tutor list. ;-)

Skip Montanaro	| Mojam: "Uniting the World of Music" http://www.mojam.com/
skip@mojam.com  | Musi-Cal: http://www.musi-cal.com/
518-372-5583



From da@ski.org  Mon Mar 29 06:03:11 1999
From: da@ski.org (David Ascher)
Date: Sun, 28 Mar 1999 22:03:11 -0800 (Pacific Standard Time)
Subject: [Tutor] Re: Listing web contents
In-Reply-To: <199903271311.IAA28831@eric.cnri.reston.va.us>
Message-ID: <Pine.WNT.4.05.9903282200480.163-100000@david.ski.org>

On Sat, 27 Mar 1999, Guido van Rossum wrote:

> PS.  To the tutors.  I see no significant difference between the tutor
> list and the help list.  Perhaps tutor should be merged back into
> help?

Well, I think there's a difference, but perhaps it's too soon to tell. The
biggest difference IMHO is that the tutor list is public and subscribed to
by both tutors and novices -- and my hope is that some of the novices
listening on the exchanges can learn from them, which doesn't happen w/
the help-list because of its relatively private nature (which I think is
useful for some).

Is that happening?  I can't tell -- maybe some of the novices on the list
can let us know.

--david ascher





From wilson@chemsun.chem.umn.edu  Mon Mar 29 06:23:35 1999
From: wilson@chemsun.chem.umn.edu (Tim Wilson)
Date: Mon, 29 Mar 1999 00:23:35 -0600 (CST)
Subject: [Tutor] parsing chemical formula
Message-ID: <Pine.BSF.3.96.990329001246.12110B-100000@chemsun.chem.umn.edu>

Greetings all:

I'd like to write a small Python app to act as a command line molecular
weight calculator. I'm a Python beginner, and I'm still in the planning
stage on this one. Specifically, I'd like to get some expert opinions on
the best way to parse the chemical formula to extract the type and number
of atoms. An example (and chemistry refresher):

H2SO4 contains 2 H, 1 S, 4 O atoms
Mg(NO3)2 contains 1 Mg, 2 N, 6 O atoms (watch those parentheses!)

Ideally, the user would run the program like this:

$ molwt H2O
The molecular weight of H2O is 18.02 g/mol.
$

I've constructed a dictionary containing all of the element symbols and
molecular weights. What type of data structure would be most appropriate
for temporarily holding the number and type of atoms in the formula before
the total mol. weights is calculated?

Any other suggestions? I think this might be a nice little app that could
be very useful.

-Tim
(At least that's what some people call me.)

--
Timothy D. Wilson			"A little song, a little dance,
University of MN, chem. dept.		a little seltzer down your 
wilson@chem.umn.edu			pants."   -Chuckles the Clown
Phone: (612) 625-9828                       as eulogized by Ted Baxter



From DOUGS@oceanic.com  Mon Mar 29 08:56:55 1999
From: DOUGS@oceanic.com (Doug Stanfield)
Date: Sun, 28 Mar 1999 22:56:55 -1000
Subject: [Tutor] Re: Listing web contents
Message-ID: <5650A1190E4FD111BC7E0000F8034D264A9EAB@HUINA>

Guido,

I believe there is a need for the public tutor list.  I still consider
myself a novice, and probably will be for the rest of my programming days.
I'm on record in c.l.py advocating a different forum for those of us without
the concentration of effort or otherwise the wherewithal required to
progress to guru-dom.  My lack of progress is because my work keeps me from
being a programmer.  Yet I have problems that need to be solved
programmatically.  Python has taken me further with less effort than any
other 'way'.  I'm one of those that will be filling in the third or fourth
level down on the pyramid as Python spreads further through the computing
community.

There is a difference between documenting something and explaining it.  Also
between clarifying using the jargon of programming theory or language
comparisons, and teaching the fundamental or elementary use of Python.
There's definately a difference between a reference 'bot and an educator.  I
see this as the difference between c.l.py and the tutor list.  And because
the tutor list is public instead of hidden it is generating that atmosphere
of trusting collegial discussion that leads to the 'ah ha' reaction.

Someone once told me that an educator was someone who could correctly answer
a question at least three uniquely different ways.  The other necessary
ingredient is the empathy to know which answer most resonates with the
students current understanding.  Personally I feel the empathy on the tutor
list, but lacking that, it's most helpful to hear all the answers and all
the perspectives.  For me that most often leads to a higher level of
comprehension.

The nature of your question implied merging the tutor-list into the
anonymous private answer help system.  Perhaps you meant the opposite.  If
there could only be one I'd choose the tutor-list, but this email should be
plenty of evidence that I don't feel the need for anonymity.  Others must so
I'd say both forums have their place.

-Doug-

> -----Original Message-----
> From: David Ascher [mailto:da@ski.org]
> Sent: Sunday, March 28, 1999 8:03 PM
> To: Guido van Rossum
> Cc: tutor@python.org
> Subject: Re: [Tutor] Re: Listing web contents
> 
> 
> On Sat, 27 Mar 1999, Guido van Rossum wrote:
> 
> > PS.  To the tutors.  I see no significant difference 
> between the tutor
> > list and the help list.  Perhaps tutor should be merged back into
> > help?
> 
> Well, I think there's a difference, but perhaps it's too soon 
> to tell. The
> biggest difference IMHO is that the tutor list is public and 
> subscribed to
> by both tutors and novices -- and my hope is that some of the novices
> listening on the exchanges can learn from them, which doesn't 
> happen w/
> the help-list because of its relatively private nature (which 
> I think is
> useful for some).
> 
> Is that happening?  I can't tell -- maybe some of the novices 
> on the list
> can let us know.
> 
> --david ascher
> 
> 
> 
> 
> _______________________________________________
> Tutor maillist  -  Tutor@python.org
> http://www.python.org/mailman/listinfo/tutor
> 


From steve@estel.uindy.edu  Mon Mar 29 11:07:54 1999
From: steve@estel.uindy.edu (Steve Spicklemire)
Date: Mon, 29 Mar 1999 06:07:54 -0500 (EST)
Subject: [Tutor] parsing chemical formula
In-Reply-To: <Pine.BSF.3.96.990329001246.12110B-100000@chemsun.chem.umn.edu> (message from Tim Wilson on Mon, 29 Mar 1999 00:23:35 -0600 (CST))
Message-ID: <199903291107.GAA04009@estel.uindy.edu>


I guess we're neglecting the mass defect due to the chemical
binding energy. 

;-)

How about something like:

----------------------------------------------------------------------

# I'm making these up.... I really don't know the correct masses off the top...
#

ElementDict = {'H':1.0, 'He':4.0, 'Li':6.0, 'O':16.0 }  # and on and on  .....

class ElementContainer:

    def __init__(self, name, count):
	self.name = name
	self.count = count


class Molecule:
    
    elementList = None
    massDefect = None   # just in case we want to get fancy...

    def addElement(self, name, count):

	if self.elementList is None:
	    self.elementList = []    # a list allows multiple instances of ElementContainers
	                             # with the same element...

	self.elementList.append(ElementContainer(name, count))

    def calcWeight(self):
	weight = 0.0

	for element in self.elementList:
	    weight = weight + element.count*ElementDict[element.name]

	if self.massDefect is not None:
	    weight = weight - massDefect

	return weight


if __name__=='__main__':
    m = Molecule()

    m.addElement('H',2)
    m.addElement('O',1)

    print "This damp example has a result of: ", m.calcWeight()


----------------------------------------------------------------------
-steve





From jlcos@accessone.com  Mon Mar 29 14:04:45 1999
From: jlcos@accessone.com (Jon Cosby)
Date: Mon, 29 Mar 1999 06:04:45 -0800
Subject: [Tutor] Re: Listing web contents
Message-ID: <01be79ed$195eb600$5b802bd1@jlcos>


>I'm assuming the URL points to an HTML document, and what you really
>want is a listing of URLs that the given URL refers to.
>
>In this case, you can cook something up using Python's HTML parsing
>library module (htmllib).
>
>I'm guessing that what you area really looking for is writing an
>automated tool that browses a tree of related pages on the web.
>In this case, please have a look at webchecker in the Python source
>distribution, Tools/webchecker/.
>

Websucker may be what I'm looking for. I'm trying to write a simple search
engine; can you give me a hint as to how to edit websucker to return a list
of web contents, rather than downloading the whole site?

Thanks,

Jon Cosby



From guido@CNRI.Reston.VA.US  Mon Mar 29 15:14:30 1999
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Mon, 29 Mar 1999 10:14:30 -0500
Subject: [Tutor] Re: Listing web contents
In-Reply-To: Your message of "Mon, 29 Mar 1999 06:04:45 PST."
 <01be79ed$195eb600$5b802bd1@jlcos>
References: <01be79ed$195eb600$5b802bd1@jlcos>
Message-ID: <199903291514.KAA00524@eric.cnri.reston.va.us>

> Websucker may be what I'm looking for. I'm trying to write a simple search
> engine; can you give me a hint as to how to edit websucker to return a list
> of web contents, rather than downloading the whole site?

Sorry, I'm not very good at answering questions of this kind -- I'm
simply too busy to sit down and figure it out.  Basically, reading the
source it should be easy enough to figure out which method saves the
data and replace it (in a subclass) with one that indexes it.  Other
tutors may have more constructive help!

(PS I take it back that the tutor list should be merged with the help
list -- maybe vice versa...)

--Guido van Rossum (home page: http://www.python.org/~guido/)


From wilson@chemsun.chem.umn.edu  Mon Mar 29 15:51:44 1999
From: wilson@chemsun.chem.umn.edu (Tim Wilson)
Date: Mon, 29 Mar 1999 09:51:44 -0600 (CST)
Subject: [Tutor] parsing chemical formula
In-Reply-To: <199903291107.GAA04009@estel.uindy.edu>
Message-ID: <Pine.BSF.3.96.990329094231.22014A-100000@chemsun.chem.umn.edu>

On Mon, 29 Mar 1999, Steve Spicklemire wrote:

Steve, thanks for the example. I'm still a little intimidated by the OOP
features that Python offers. I should probably just bit the bullet and dig
in and learn it. I think I understand how a list would be useful to store
the atoms until the total mass can be calculated. I don't see where you
parse the user input here. I'll be more specific: How will the program be
able to figure out how many atoms of each type are in a molecule like
(NH4)3PO4? How will it know the difference between CO (carbon monoxide)
and Co (a cobalt atom)? It seems to be that figuring out the difference
between Co and CO and interpreting the parentheses correctly is fairly
tricky (at least for me). Any other suggestions would be appreciated.

-Tim

Steve's sample code follows:
> # I'm making these up.... I really don't know the correct masses off the top...
> #
> 
> ElementDict = {'H':1.0, 'He':4.0, 'Li':6.0, 'O':16.0 }  # and on and on  .....
> 
> class ElementContainer:
> 
>     def __init__(self, name, count):
> 	self.name = name
> 	self.count = count
> 
> 
> class Molecule:
>     
>     elementList = None
>     massDefect = None   # just in case we want to get fancy...
> 
>     def addElement(self, name, count):
> 
> 	if self.elementList is None:
> 	    self.elementList = []    # a list allows multiple instances of ElementContainers
> 	                             # with the same element...
> 
> 	self.elementList.append(ElementContainer(name, count))
> 
>     def calcWeight(self):
> 	weight = 0.0
> 
> 	for element in self.elementList:
> 	    weight = weight + element.count*ElementDict[element.name]
> 
> 	if self.massDefect is not None:
> 	    weight = weight - massDefect
> 
> 	return weight
> 
> 
> if __name__=='__main__':
>     m = Molecule()
> 
>     m.addElement('H',2)
>     m.addElement('O',1)
> 
>     print "This damp example has a result of: ", m.calcWeight()
> 
> 
> ----------------------------------------------------------------------
> -steve
> 
> 
> 
> 

--
Timothy D. Wilson			"A little song, a little dance,
University of MN, chem. dept.		a little seltzer down your 
wilson@chem.umn.edu			pants."   -Chuckles the Clown
Phone: (612) 625-9828                       as eulogized by Ted Baxter



From M.Faassen@vet.uu.nl  Mon Mar 29 16:34:41 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Mon, 29 Mar 1999 18:34:41 +0200
Subject: [Tutor] parsing chemical formula
References: <Pine.BSF.3.96.990329094231.22014A-100000@chemsun.chem.umn.edu>
Message-ID: <36FFABA1.983ED48F@pop.vet.uu.nl>

Tim Wilson wrote:
> 
> I'm still a little intimidated by the OOP
> features that Python offers. I should probably just bit the bullet and dig
> in and learn it.

For starts, you might try thinking of a class instance as a Python
dictionary.

For instance the dictionary:

    # make a dictionary
    aFoo = {}
    # fill dictionary with data
    aFoo['one'] = 1
    aFoo['two'] = 2
    aFoo['three'] = 3

is quite similar to the class:

    # make a class (and also say somehow how the data inside is
structured)
    class Foo:
        def __init__(self, one, two, three):
            self.one = one
            self.two = two
            self.three = three

    # fill an instance of Foo (aFoo) with data
    aFoo = Foo(1, 2, 3)    

Of course, initialization in __init__ isn't necessary, you could do:

    class Foo:
        pass # empty class

    aFoo = Foo()
    aFoo.one = 1
    aFoo.two = 2
    aFoo.three = 3

But the nice thing about a class (as compared to a dictionary) is that
it's easy to add functions to a class that actually do something with
the data stored inside (for instance, do some calculation). By
initializing (lots of) the data in an __init__ function, you're sure
these data members are there during the class's lifetime, as __init__ is
always executed when the class is created:

    class Foo:
        def __init__(self, one, two, three):
            self.one = one
            self.two = two
            self.three = three

        def add_all(self):
            return self.one + self.two + self.three

    aFoo = Foo(1, 2, 3)
    print aFoo.add_all() # prints 6
    aBar = Foo(3, 3, 3) 
    print aBar.add_all() # prints 9

Of course, it's possible to write functions that do this with
dictionaries, but classes add some nice extra structure that is helpful.
They can be useful to bundle data and the functions that operate on that
data together, without the outside world needing to know what's going on
exactly inside the data and the functions (data hiding). Classes of
course also offer inheritance, but that's for later.

> I think I understand how a list would be useful to store
> the atoms until the total mass can be calculated. I don't see where you
> parse the user input here. 

> I'll be more specific: 

> How will it know the difference between CO (carbon monoxide)
> and Co (a cobalt atom)?

Hmm. 

You have this dictionary with as the keys the various element names (and
as value their mass), let's call it 'elements', and a string describing
a molecule called 'molecule'. An  approach may be:

# untested code! Doesn't do boundary checking! is probably slow!
def getWeightForNextElement(molecule, elements):
    # assumption: all elements are a maximum of two characters, where
the first 
    # is a capital, and the second is lowercase

    # if 'molecule' doesn't start with an atom identifier at all we
return 'None'
    if molecule[0] not in string.uppercase:
        return None
    if molecule[1] not in string.lowercase:
        # okay, we're dealing with a single char element, look it up:
        if elements.has_key(molecule[0]):
            return (elements[molecule[0]), 1) # return weight and length
of what we read
        else:
            return None # not a known element
    else:
        # okay, we're dealing with a two char element:
        if elements.has_key(molecule[0:1]):
            return (elements[molecule[0:1]), 2)  # return weight and
length of str we read
        else:
            return None # not a known element

This function, if it works at all :), could be fed with a molecule
string. If the function doesn't return None and thus recognizes the
weight, it'll return the weight value, and the length (1 or 2) of the
characters it read. You can then strip those characters from the front
of the string, feed in the string again, and get the weight of the next
character, until you read the string. Of course it doesn't work with
'()' or numbers yet.
            
> How will the program be
> able to figure out how many atoms of each type are in a molecule like
> (NH4)3PO4? 

Numbers first. You can adapt the previous function (better rewrite it
anyway, it was just a bad first attempt :) so that it recognizes if
digits are involved (string.digits). What it should do is that as soon
as it encounters a digit, it scans if any digits follow. It'll compose a
string of all digits read. It then should convert (with int(), let's
say) this string to an actual amount. It should then somehow notify the
calling function that it read a number, and the value of this number.
Since the function doesn't support this I suggested rewriting. Better
perhaps to do any weight calculations later anyway, and just return the
elements read (not their weights), too.

Parenthesis. You could do something like this:

* If you read a '(' parenthesis, add create a new empty list of
elements, and add this to the list of elements read.

* Do this whenever you see another '(' (a nested '('). So you might get
a list nested in a list nested in a list, if you have a lot of ((()))
stuff.

* Until you read a ')' parenthesis, add any read elements to the current
list (or their mass). If you read numbers, of course do the right
multiplications, or simply add as many elements to the current list as
the number indicates.

When you've read the string (and the string makes sense syntactically;
doesn't contain unknown elements or weird parenthesis such as '(()'),
you'll end up with a big master list of elements (or mass) that may
contain sublists of a similar structure.

Now you want to add the weight of it all:

# untested!
def add_everything(master_list, elements):
    sum = 0.0 
    for el in master_list:
        if el is types.ListType:
            # recursion; add everything in the sublist and add it to the
master sum
            sum = sum + add_everything(el, elements)
        else:
            sum = sum + elements[el]
    return sum

A whole long post. I hope I'm making sense somewhat and that it helps.
:) Please let us all know!

Regards,

Martijn


From bwinton@tor.dhs.org  Tue Mar 30 01:41:07 1999
From: bwinton@tor.dhs.org (Blake Winton)
Date: Mon, 29 Mar 1999 20:41:07 -0500 (EST)
Subject: [Tutor] parsing chemical formula
In-Reply-To: <Pine.BSF.3.96.990329094231.22014A-100000@chemsun.chem.umn.edu> from "Tim Wilson" at Mar 29, 99 09:51:44 am
Message-ID: <199903300141.UAA25612@tor.dhs.org>

> On Mon, 29 Mar 1999, Steve Spicklemire wrote:
> don't see where you parse the user input here. I'll be more specific:
> How will the program be able to figure out how many atoms of each type
> are in a molecule like (NH4)3PO4? How will it know the difference
> between CO (carbon monoxide) and Co (a cobalt atom)? It seems to be
> that figuring out the difference between Co and CO and interpreting
> the parentheses correctly is fairly tricky (at least for me). Any
> other suggestions would be appreciated.

I've been playing around with John Aycock's "Little Language Framework"
(at http://www.csc.uvic.ca/~aycock/), and it looks pretty much perfect
for what you're trying to do, so I whipped a quick little something up.

WARNING!!!  :  It's not really suitable for the tutor list, since it
               relies on a non-standard Python module, and compiler
               technology isn't really beginner material.  But it works,
               so far.  I can try to explain what I did, if anyone
               thinks it'll be useful, but I think the explanation would
               be better kept to email.

Later,
Blake.


From bwinton@tor.dhs.org  Tue Mar 30 01:47:26 1999
From: bwinton@tor.dhs.org (Blake Winton)
Date: Mon, 29 Mar 1999 20:47:26 -0500 (EST)
Subject: [Tutor] parsing chemical formula
In-Reply-To: <Pine.BSF.3.96.990329094231.22014A-100000@chemsun.chem.umn.edu> from "Tim Wilson" at Mar 29, 99 09:51:44 am
Message-ID: <199903300147.UAA25673@tor.dhs.org>

> On Mon, 29 Mar 1999, Steve Spicklemire wrote:
> Any other suggestions would be appreciated.

And of course, I forget to tell you all where the solution is...  :P

Written by me:
http://tor.dhs.org/%7Ebwinton/python/chemweight.py              # My program

Writtne by John:
http://tor.dhs.org/%7Ebwinton/python/generic.py                 # The framework
http://tor.dhs.org/%7Ebwinton/python/framework-0.3/doc/faq.html # A FAQ

Sorry about that...
Blake.

P.S. John, if you're reading this, I couldn't find a "Token" class in
     generic.py.  Is it in an example file, or should there be a stub
     in generic.py?  The docs seem to suggest the latter.


From tim_one@email.msn.com  Tue Mar 30 06:50:10 1999
From: tim_one@email.msn.com (Tim Peters)
Date: Tue, 30 Mar 1999 01:50:10 -0500
Subject: [Tutor] parsing chemical formula
In-Reply-To: <Pine.BSF.3.96.990329001246.12110B-100000@chemsun.chem.umn.edu>
Message-ID: <000201be7a79$8eb969e0$ee9e2299@tim>

[Tim Wilson]
> I'd like to write a small Python app to act as a command line molecular
> weight calculator. I'm a Python beginner, and I'm still in the planning
> stage on this one. Specifically, I'd like to get some expert opinions on
> the best way to parse the chemical formula to extract the type and number
> of atoms. ...

Well, the syntax of a formula is recursively defined:  each chunk of the
expression is either an element name, or is itself an expression enclosed in
parentheses (that's the recursion <wink>), and in either case followed by an
optional "repeat count".

Parsing isn't easy, but can be learned.  I'm going to attach a complete
solution to this one, allowing you to type e.g.

D:\Python>python misc/molw.py
? H2O
input must have two fields
? molw H2O
molecular weight 18.0152
? syms H2O
H (Hydrogen): 2
O (Oxygen): 1
? molw NaCl
molecular weight 58.44277
? syms (H2O4)12
H (Hydrogen): 24
O (Oxygen): 48
? PbUr
input must have two fields
? molw PbU
molecular weight 445.229
? syms PbU
Pb (Lead): 1
U (Uranium): 1
? molw Mg(NO3)2
molecular weight 148.3148
? syms Mg(NO3)2
Mg (Magnesium): 1
N (Nitrogen): 2
O (Oxygen): 6
? molw ClAp
'Ap' is not an element symbol:
ClAp
  ^

?

The parsing technique here is called "recursive descent with one token
lookahead".  That may all sound like gibberish now, but once you understand
the (simple) code, each word in that will be seen to have a definite
meaning.  The structure of the parsing code matches the informal English
recursive definition above very closely.  That's the great advantage of
recursive descent:  it's inuitive.

You'll find that it won't accept any illegal formulas, but that sometimes
the error msgs it produces are odd.  This should give you a lot of sympathy
for Guido's job <0.9 wink>.

Apart from the parser, there's a Tokenizer class here that's a bit of
overkill in this particular context.  The tokenizer simply looks at "the
next" piece of the formula, and classifies the first chunk of it as to
whether it looks like a parenthesis, element name, repeat count, or end of
input.  The *kind* of token is stored in global ttype, and the *value* of
the token is stored in global tvalue.  The parsing code makes its decisions
based on ttype, and uses tvalue as needed to extract specific information.

This is a classic structure for parsers, and works very well in practice --
provided you get used to it first, and don't get too terribly ambitious.
Before the advent of machine-generated table-driven parsers, entire
compilers (e.g. Pascal's) were written "by hand" this way.  It's easy enough
to pick up that everyone ought to learn how to do it -- which is why I'm
posting the whole thing to the tutor list <wink>.

The rest of it is simpler, and should remind you of the series/parallel
circuit example Gordon posted to c.l.py a while back.  A formula is a
sequence of elements and subformulas, and an ElementSequence class models
that as a list (a list of what?  of Elements and other ElementSequences!
again this matches the English description very closely).  It's trivial for
an Element to report its own weight, and an ElementSequence just has to ask
its contained guys for their weights and sum them up.

recursion-is-your-friend-because-nature-is-recursive-ly y'rs  - tim

# symbol, name, atomic number, molecular weight
_data = r"""'Ac', 'Actinium', 89, 227
'Ag', 'Silver', 47, 107.868
'Al', 'Aluminum', 13, 26.98154
'Am', 'Americium', 95, 243
'Ar', 'Argon', 18, 39.948
'As', 'Arsenic', 33, 74.9216
'At', 'Astatine', 85, 210
'Au', 'Gold', 79, 196.9665
'B', 'Boron', 5, 10.81
'Ba', 'Barium', 56, 137.33
'Be', 'Beryllium', 4, 9.01218
'Bi', 'Bismuth', 83, 208.9804
'Bk', 'Berkelium', 97, 247
'Br', 'Bromine', 35, 79.904
'C', 'Carbon', 6, 12.011
'Ca', 'Calcium', 20, 40.08
'Cd', 'Cadmium', 48, 112.41
'Ce', 'Cerium', 58, 140.12
'Cf', 'Californium', 98, 251
'Cl', 'Chlorine', 17, 35.453
'Cm', 'Curium', 96, 247
'Co', 'Cobalt', 27, 58.9332
'Cr', 'Chromium', 24, 51.996
'Cs', 'Cesium', 55, 132.9054
'Cu', 'Copper', 29, 63.546
'Dy', 'Dysprosium', 66, 162.50
'Er', 'Erbium', 68, 167.26
'Es', 'Einsteinium', 99, 254
'Eu', 'Europium', 63, 151.96
'F', 'Fluorine', 9, 18.998403
'Fe', 'Iron', 26, 55.847
'Fm', 'Fermium', 100, 257
'Fr', 'Francium', 87, 223
'Ga', 'Gallium', 31, 69.735
'Gd', 'Gadolinium', 64, 157.25
'Ge', 'Germanium', 32, 72.59
'H', 'Hydrogen', 1, 1.0079
'He', 'Helium', 2, 4.0026
'Hf', 'Hafnium', 72, 178.49
'Hg', 'Mercury', 80, 200.59
'Ho', 'Holmium', 67, 164.9304
'I', 'Iodine', 53, 126.9045
'In', 'Indium', 49, 114.82
'Ir', 'Iridium', 77, 192.22
'K', 'Potassium', 19, 39.0983
'Kr', 'Krypton', 36, 83.80
'La', 'Lanthanum', 57, 138.9055
'Li', 'Lithium', 3, 6.94
'Lr', 'Lawrencium', 103, 260
'Lu', 'Lutetium', 71, 174.96
'Md', 'Mendelevium', 101, 258
'Mg', 'Magnesium', 12, 24.305
'Mn', 'Manganese', 25, 54.9380
'Mo', 'Molybdenum', 42, 95.94
'N', 'Nitrogen', 7, 14.0067
'Na', 'Sodium', 11, 22.98977
'Nb', 'Niobium', 41, 92.9064
'Nd', 'Neodymium', 60, 144.24
'Ne', 'Neon', 10, 20.17
'Ni', 'Nickel', 28, 58.71
'No', 'Nobelium', 102, 259
'Np', 'Neptunium', 93, 237.0482
'O', 'Oxygen', 8, 15.9994
'Os', 'Osmium', 76, 190.2
'P', 'Phosphorous', 15, 30.97376
'Pa', 'Proactinium', 91, 231.0359
'Pb', 'Lead', 82, 207.2
'Pd', 'Palladium', 46, 106.4
'Pm', 'Promethium', 61, 145
'Po', 'Polonium', 84, 209
'Pr', 'Praseodymium', 59, 140.9077
'Pt', 'Platinum', 78, 195.09
'Pu', 'Plutonium', 94, 244
'Ra', 'Radium', 88, 226.0254
'Rb', 'Rubidium', 37, 85.467
'Re', 'Rhenium', 75, 186.207
'Rh', 'Rhodium', 45, 102.9055
'Rn', 'Radon', 86, 222
'Ru', 'Ruthenium', 44, 101.07
'S', 'Sulfur', 16, 32.06
'Sb', 'Antimony', 51, 121.75
'Sc', 'Scandium', 21, 44.9559
'Se', 'Selenium', 34, 78.96
'Si', 'Silicon', 14, 28.0855
'Sm', 'Samarium', 62, 150.4
'Sn', 'Tin', 50, 118.69
'Sr', 'Strontium', 38, 87.62
'Ta', 'Tantalum', 73, 180.947
'Tb', 'Terbium', 65, 158.9254
'Tc', 'Technetium', 43, 98.9062
'Te', 'Tellurium', 52, 127.60
'Th', 'Thorium', 90, 232.0381
'Ti', 'Titanium', 22, 47.90
'Tl', 'Thallium', 81, 204.37
'Tm', 'Thulium', 69, 168.9342
'U', 'Uranium', 92, 238.029
'Unh', 'Unnilhexium', 106, 263
'Unp', 'Unnilpentium', 105, 260
'Unq', 'Unnilquadium', 104, 260
'Uns', 'Unnilseptium', 107, 262
'V', 'Vanadium', 23, 50.9415
'W', 'Tungsten', 74, 183.85
'Xe', 'Xenon', 54, 131.30
'Y', 'Yttrium', 39, 88.9059
'Yb', 'Ytterbium', 70, 173.04
'Zn', 'Zinc', 30, 65.38
'Zr', 'Zirconium', 40, 91.22"""

class Element:
    def __init__(self, symbol, name, atomicnumber, molweight):
        self.sym = symbol
        self.name = name
        self.ano = atomicnumber
        self.mw = molweight

    def getweight(self):
        return self.mw

    def addsyms(self, weight, result):
        result[self.sym] = result.get(self.sym, 0) + weight

def build_dict(s):
    import string
    answer = {}
    for line in string.split(s, "\n"):
        symbol, name, num, weight = eval(line)
        answer[symbol] = Element(symbol, name, num, weight)
    return answer

sym2elt = build_dict(_data)
del _data

class ElementSequence:
    def __init__(self, *seq):
        self.seq = list(seq)
        self.count = 1

    def append(self, thing):
        self.seq.append(thing)

    def getweight(self):
        sum = 0.0
        for thing in self.seq:
            sum = sum + thing.getweight()
        return sum * self.count

    def set_count(self, n):
        self.count = n

    def __len__(self):
        return len(self.seq)

    def addsyms(self, weight, result):
        totalweight = weight * self.count
        for thing in self.seq:
            thing.addsyms(totalweight, result)

    def displaysyms(self):
        result = {}
        self.addsyms(1, result)
        items = result.items()
        items.sort()
        for sym, count in items:
            print sym, "(" + sym2elt[sym].name + "):", count

NAME, NUM, LPAREN, RPAREN, EOS = range(5)
import re
_lexer = re.compile(r"[A-Z][a-z]*|\d+|[()]|<EOS>").match
del re

class Tokenizer:
    def __init__(self, input):
        self.input = input + "<EOS>"
        self.i = 0

    def gettoken(self):
        global ttype, tvalue
        self.lasti = self.i
        m = _lexer(self.input, self.i)
        if m is None:
            self.error("unexpected character")
        self.i = m.end()
        tvalue = m.group()
        if tvalue == "(":
            ttype = LPAREN
        elif tvalue == ")":
            ttype = RPAREN
        elif tvalue == "<EOS>":
            ttype = EOS
        elif "0" <= tvalue[0] <= "9":
            ttype = NUM
            tvalue = int(tvalue)
        else:
            ttype = NAME

    def error(self, msg):
        emsg = msg + ":\n"
        emsg = emsg + self.input[:-5] + "\n"  # strip <EOS>
        emsg = emsg + " " * self.lasti + "^\n"
        raise ValueError(emsg)

def parse(s):
    global t, ttype, tvalue
    t = Tokenizer(s)
    t.gettoken()
    seq = parse_sequence()
    if ttype != EOS:
        t.error("expected end of input")
    return seq

def parse_sequence():
    global t, ttype, tvalue
    seq = ElementSequence()
    while ttype in (LPAREN, NAME):
        # parenthesized expression or straight name
        if ttype == LPAREN:
            t.gettoken()
            thisguy = parse_sequence()
            if ttype != RPAREN:
                t.error("expected right paren")
            t.gettoken()
        else:
            assert ttype == NAME
            if sym2elt.has_key(tvalue):
                thisguy = ElementSequence(sym2elt[tvalue])
            else:
                t.error("'" + tvalue + "' is not an element symbol")
            t.gettoken()
        # followed by optional count
        if ttype == NUM:
            thisguy.set_count(tvalue)
            t.gettoken()
        seq.append(thisguy)
    if len(seq) == 0:
        t.error("empty sequence")
    return seq

import string
while 1:
    x = raw_input("? ")
    fields = string.split(x)
    if len(fields) != 2:
        print "input must have two fields"
        continue
    action, formula = fields
    ok = 0
    try:
        seq = parse(formula)
        ok = 1
    except ValueError, detail:
        print str(detail)
    if not ok:
        continue
    if action == "molw":
        print "molecular weight", seq.getweight()
    elif action == "syms":
        seq.displaysyms()
    else:
        print "unknown action:", action




From tismer@appliedbiometrics.com  Tue Mar 30 11:53:48 1999
From: tismer@appliedbiometrics.com (Christian Tismer)
Date: Tue, 30 Mar 1999 13:53:48 +0200
Subject: [Tutor] parsing chemical formula
References: <000201be7a79$8eb969e0$ee9e2299@tim>
Message-ID: <3700BB4C.2C430E63@appliedbiometrics.com>


Tim Peters wrote:
...

> NAME, NUM, LPAREN, RPAREN, EOS = range(5)

As I see this idiom of creating ENUM-alike constants
appear again (see doctest), this deserves an entry in 
some howto. Tim, when did you start using it?
Very elegant.

ciao - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home


From M.Faassen@vet.uu.nl  Tue Mar 30 12:02:54 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Tue, 30 Mar 1999 14:02:54 +0200
Subject: [Tutor] parsing chemical formula
References: <000201be7a79$8eb969e0$ee9e2299@tim> <3700BB4C.2C430E63@appliedbiometrics.com>
Message-ID: <3700BD6E.84DA979@pop.vet.uu.nl>

Christian Tismer wrote:
> 
> Tim Peters wrote:
> ...
> 
> > NAME, NUM, LPAREN, RPAREN, EOS = range(5)
> 
> As I see this idiom of creating ENUM-alike constants
> appear again (see doctest), this deserves an entry in
> some howto. Tim, when did you start using it?
> Very elegant.

It's a neat idiom. I'm not sure where I got it from (I've used it too),
but I recall a while back I was pondering the problem. You see, I hate
counting, and one needs to *count* to do this trick with range. C's
'enum' doesn't have this problem. So I tried to figure out an elegant
way to do something like:

enum(NAME, NUM, LPAREN, RPAREN, EOS)

but couldn't come up with anything that worked well. The main problem is
of course that NAME etc simply aren't defined, so you get an exception.
You can catch that exception of course, and then define, but so far
that's still a kludge.

Perhaps: enum('NAME', 'NUM', 'LPAREN', 'RPAREN', 'EOS') could
work..still, that is too much typing. :)

Of course this doesn't belong on tutor but in the newsgroup, really, but
I felt so much mental exertion on my part deserved some mention
somewhere, and this was a good opportunity. :)

Regards,

Martijn


From tismer@appliedbiometrics.com  Tue Mar 30 13:17:40 1999
From: tismer@appliedbiometrics.com (Christian Tismer)
Date: Tue, 30 Mar 1999 15:17:40 +0200
Subject: [Tutor] parsing chemical formula
References: <000201be7a79$8eb969e0$ee9e2299@tim> <3700BB4C.2C430E63@appliedbiometrics.com> <3700BD6E.84DA979@pop.vet.uu.nl>
Message-ID: <3700CEF4.D82CF0C4@appliedbiometrics.com>


Martijn Faassen wrote:
> 
> Christian Tismer wrote:
> >
> > Tim Peters wrote:
> > ...
> >
> > > NAME, NUM, LPAREN, RPAREN, EOS = range(5)
> >
> > As I see this idiom of creating ENUM-alike constants
> > appear again (see doctest), this deserves an entry in
> > some howto. Tim, when did you start using it?
> > Very elegant.
> 
> It's a neat idiom. I'm not sure where I got it from (I've used it too),
> but I recall a while back I was pondering the problem. You see, I hate
> counting, and one needs to *count* to do this trick with range. C's
> 'enum' doesn't have this problem. So I tried to figure out an elegant
> way to do something like:
> 
> enum(NAME, NUM, LPAREN, RPAREN, EOS)
> 
> but couldn't come up with anything that worked well. The main problem is
> of course that NAME etc simply aren't defined, so you get an exception.
> You can catch that exception of course, and then define, but so far
> that's still a kludge.
> 
> Perhaps: enum('NAME', 'NUM', 'LPAREN', 'RPAREN', 'EOS') could
> work..still, that is too much typing. :)
> 
> Of course this doesn't belong on tutor but in the newsgroup, really, but
> I felt so much mental exertion on my part deserved some mention
> somewhere, and this was a good opportunity. :)

:-))

Well, how 'bout this? 
You can even save to type those ugly commas:

>>> def enum(tokens, base=0):
... 	import string
... 	lis = string.split(tokens)
... 	g = globals()
... 	for i in range(len(lis)):
... 	    g[lis[i]] = i+base
... 
>>> enum("ONE TWO THREE", 1)
>>> ONE, TWO, THREE
(1, 2, 3)
>>> 

ciao - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home


From M.Faassen@vet.uu.nl  Tue Mar 30 15:23:11 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Tue, 30 Mar 1999 17:23:11 +0200
Subject: [Tutor] parsing chemical formula
References: <000201be7a79$8eb969e0$ee9e2299@tim> <3700BB4C.2C430E63@appliedbiometrics.com> <3700BD6E.84DA979@pop.vet.uu.nl> <3700CEF4.D82CF0C4@appliedbiometrics.com>
Message-ID: <3700EC5F.6B8E0490@pop.vet.uu.nl>

Christian Tismer wrote:
> 
> Martijn Faassen wrote:
[enum thoughts]
> :-))
> 
> Well, how 'bout this?
> You can even save to type those ugly commas:
> 
> >>> def enum(tokens, base=0):
> ...     import string
> ...     lis = string.split(tokens)
> ...     g = globals()
> ...     for i in range(len(lis)):
> ...         g[lis[i]] = i+base
> ...
> >>> enum("ONE TWO THREE", 1)
> >>> ONE, TWO, THREE
> (1, 2, 3)
> >>>

Cool, I hadn't thought of using string.split to reduce the amount of
quotes (and commas!). Still not exactly of the elegance of:

    ONE, TWO, THREE = range(3) # this *looks* like Python code (as it is
:)

but almost there, and no counting!

Fun!

Regards,

Martijn


From tismer@appliedbiometrics.com  Tue Mar 30 16:03:48 1999
From: tismer@appliedbiometrics.com (Christian Tismer)
Date: Tue, 30 Mar 1999 18:03:48 +0200
Subject: [Tutor] parsing chemical formula
References: <000201be7a79$8eb969e0$ee9e2299@tim> <3700BB4C.2C430E63@appliedbiometrics.com> <3700BD6E.84DA979@pop.vet.uu.nl> <3700CEF4.D82CF0C4@appliedbiometrics.com> <3700EC5F.6B8E0490@pop.vet.uu.nl>
Message-ID: <3700F5E4.E6231638@appliedbiometrics.com>


Martijn Faassen wrote:
> 
> Christian Tismer wrote:
> >
> > Martijn Faassen wrote:
> [enum thoughts]
> > :-))

[me, with an enum impl by strings]

> Cool, I hadn't thought of using string.split to reduce the amount of
> quotes (and commas!). Still not exactly of the elegance of:
> 
>     ONE, TWO, THREE = range(3) # this *looks* like Python code (as it is
> :)
> 
> but almost there, and no counting!

Now, if you must, how 'bout this:

>>> def make_enum(func, base):
... 	g = globals()
... 	for i in range(func.func_code.co_argcount):
... 	    g[func.func_code.co_varnames[i]] = i+base
... 	del g[func.__name__]
... 
>>> # after this, you can fake an enum like this
>>> def enum(ONE, TWO, THREE) : pass
>>> # and you activate it so:
>>> make_enum(enum, 1)
>>> # here we are:
>>> ONE, TWO, THREE
(1, 2, 3)
>>> 

I think I have to duck and cover if Timbot watches me :-)

ciao - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home


From M.Faassen@vet.uu.nl  Tue Mar 30 17:08:36 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Tue, 30 Mar 1999 19:08:36 +0200
Subject: [Tutor] parsing chemical formula
References: <000201be7a79$8eb969e0$ee9e2299@tim> <3700BB4C.2C430E63@appliedbiometrics.com> <3700BD6E.84DA979@pop.vet.uu.nl> <3700CEF4.D82CF0C4@appliedbiometrics.com> <3700EC5F.6B8E0490@pop.vet.uu.nl> <3700F5E4.E6231638@appliedbiometrics.com>
Message-ID: <37010514.177A92E5@pop.vet.uu.nl>

Christian Tismer wrote:
 
> Now, if you must, how 'bout this:
> 
> >>> def make_enum(func, base):
> ...     g = globals()
> ...     for i in range(func.func_code.co_argcount):
> ...         g[func.func_code.co_varnames[i]] = i+base
> ...     del g[func.__name__]
> ...
> >>> # after this, you can fake an enum like this
> >>> def enum(ONE, TWO, THREE) : pass
> >>> # and you activate it so:
> >>> make_enum(enum, 1)
> >>> # here we are:
> >>> ONE, TWO, THREE
> (1, 2, 3)
> >>>

Hm, this is too many lines [whine, nag, never-pleased-ly yours]. As
kludge trickery though, it's way cool!
 
> I think I have to duck and cover if Timbot watches me :-)

Indeed, Timbot is sure to catch us at this soon!

Martijn


From tismer@appliedbiometrics.com  Tue Mar 30 17:43:21 1999
From: tismer@appliedbiometrics.com (Christian Tismer)
Date: Tue, 30 Mar 1999 19:43:21 +0200
Subject: [Tutor] parsing chemical formula
References: <000201be7a79$8eb969e0$ee9e2299@tim> <3700BB4C.2C430E63@appliedbiometrics.com> <3700BD6E.84DA979@pop.vet.uu.nl> <3700CEF4.D82CF0C4@appliedbiometrics.com> <3700EC5F.6B8E0490@pop.vet.uu.nl> <3700F5E4.E6231638@appliedbiometrics.com> <37010514.177A92E5@pop.vet.uu.nl>
Message-ID: <37010D39.971056D8@appliedbiometrics.com>

Sorry, tutor list,
but I could not resist.
I will stop this now. (Ahem)

Martijn Faassen wrote:
> 
> Christian Tismer wrote:
> 
> > Now, if you must, how 'bout this:

[second try. But watch out...]

> Hm, this is too many lines [whine, nag, never-pleased-ly yours]. As
> kludge trickery though, it's way cool!
> 
> > I think I have to duck and cover if Timbot watches me :-)
> 
> Indeed, Timbot is sure to catch us at this soon!

Now I will him give a final reason to pursue me.

def enum(func):
    g = globals() ; code = func.func_code
    base = apply(func, (0,)*code.co_argcount) or 0
    for i in range(code.co_argcount):
        g[code.co_varnames[i]] = i+base

Yeees, this is hefty.
But now watch out what I got for the application:

from spinners.pirx import enum    # har har

enum(lambda ONE, TWO, THREE, FOUR, FIVE:1)

# this gives us an enumeration, based from 1. Believe me.

>>> ONE, TWO, THREE, FOUR, FIVE
(1, 2, 3, 4, 5)

Naaah? Oh yeah, now we really have a "useful" lambda example :-)))

ciao - chris.ducked.and.covered.for.the.rest.of....

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home


From tismer@appliedbiometrics.com  Tue Mar 30 18:04:35 1999
From: tismer@appliedbiometrics.com (Christian Tismer)
Date: Tue, 30 Mar 1999 20:04:35 +0200
Subject: [Tutor] parsing chemical formula
References: <000201be7a79$8eb969e0$ee9e2299@tim> <3700BB4C.2C430E63@appliedbiometrics.com> <3700BD6E.84DA979@pop.vet.uu.nl> <3700CEF4.D82CF0C4@appliedbiometrics.com> <3700EC5F.6B8E0490@pop.vet.uu.nl> <3700F5E4.E6231638@appliedbiometrics.com> <37010514.177A92E5@pop.vet.uu.nl> <37010D39.971056D8@appliedbiometrics.com>
Message-ID: <37011233.C024631A@appliedbiometrics.com>


Christian Tismer wrote:
> 
> Sorry, tutor list,
> but I could not resist.
> I will stop this now. (Ahem)

Last refinement: To make an import of enum
possible, I have to obtain the globals from the lambda:

# in somewhere.py
def enum(func):
    g = func.func_globals ; code = func.func_code
    base = apply(func, (0,)*code.co_argcount) or 0
    for i in range(code.co_argcount):
        g[code.co_varnames[i]] = i+base

# Now I can do

from somewhere import enum

enum(lambda ONE, TWO, THREE, FOUR, FIVE:1)

ciao - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home


From M.Faassen@vet.uu.nl  Tue Mar 30 18:25:28 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Tue, 30 Mar 1999 20:25:28 +0200
Subject: [Tutor] parsing chemical formula
References: <000201be7a79$8eb969e0$ee9e2299@tim> <3700BB4C.2C430E63@appliedbiometrics.com> <3700BD6E.84DA979@pop.vet.uu.nl> <3700CEF4.D82CF0C4@appliedbiometrics.com> <3700EC5F.6B8E0490@pop.vet.uu.nl> <3700F5E4.E6231638@appliedbiometrics.com> <37010514.177A92E5@pop.vet.uu.nl> <37010D39.971056D8@appliedbiometrics.com>
Message-ID: <37011718.36F37EEA@pop.vet.uu.nl>

Christian Tismer wrote:

> def enum(func):
>     g = globals() ; code = func.func_code
>     base = apply(func, (0,)*code.co_argcount) or 0
>     for i in range(code.co_argcount):
>         g[code.co_varnames[i]] = i+base
> 
> Yeees, this is hefty.
> But now watch out what I got for the application:
> 
> from spinners.pirx import enum    # har har
> 
> enum(lambda ONE, TWO, THREE, FOUR, FIVE:1)
> 
> # this gives us an enumeration, based from 1. Believe me.
> 
> >>> ONE, TWO, THREE, FOUR, FIVE
> (1, 2, 3, 4, 5)
> 
> Naaah? Oh yeah, now we really have a "useful" lambda example :-)))

This literally made me laugh out loud. :) Such ingenuity spent on my
childish demands!

Thanks, it was fun!

Martijn


From wilson@chemsun.chem.umn.edu  Tue Mar 30 22:19:06 1999
From: wilson@chemsun.chem.umn.edu (Tim Wilson)
Date: Tue, 30 Mar 1999 16:19:06 -0600 (CST)
Subject: [Tutor] chemical formula
Message-ID: <Pine.BSF.3.96.990330161536.15348A-100000@chemsun.chem.umn.edu>

Thanks to everyone who offered suggestions for my little molecular weight
app. You've given me more than enough to chew on for awhile. I plan to
study the OOP techniques that were used in creating them and see if I can
understand it. I have yet to read a good tutorial on OOP for the novice. I
find _Programming Python_ to be a little too advanced for me in that area.
I'm working my way through Guido's excellent tutorial as well, but even
there it's easy to get lost in the vocabulary. If anyone knows of some
reading I could do to get the "big picture" of OOP, please post it.

Hanging loose as usual,
Tim

--
Timothy D. Wilson			"A little song, a little dance,
University of MN, chem. dept.		a little seltzer down your 
wilson@chem.umn.edu			pants."   -Chuckles the Clown
Phone: (612) 625-9828                       as eulogized by Ted Baxter



From tim_one@email.msn.com  Wed Mar 31 06:43:38 1999
From: tim_one@email.msn.com (Tim Peters)
Date: Wed, 31 Mar 1999 01:43:38 -0500
Subject: [Tutor] parsing chemical formula
In-Reply-To: <3700BB4C.2C430E63@appliedbiometrics.com>
Message-ID: <000a01be7b41$cee41f60$f19e2299@tim>

>> NAME, NUM, LPAREN, RPAREN, EOS = range(5)

[Christian Tismer]
> As I see this idiom of creating ENUM-alike constants
> appear again (see doctest), this deserves an entry in
> some howto. Tim, when did you start using it?
> Very elegant.

I do believe I was the first to do this, sometime in the first year of
Python's life.  Hard to remember whether Guido was tickled or appalled
<wink>.  Back then you couldn't mix sequence types across an unpacked
assignment, though, so it had to be written with a list on both sides:

[NAME, NUM, LPAREN, RPAREN, EOS] = range(5)

It's nicer now.

While I normally charge hefty royalties for use of this device, I hereby
grant lifetime royalty-free licenses to all readers of the Tutor list
<wink>.

You and Martijn went on to have a lot of fun making count-free variations,
but you neglected to tell the tutorees that anything beyond this is *sick*
fun.  Sick, sick, sick!  This is the way to do it:

import enum
enum.start(100)
import A, B, C, reset500, D, E
enum.stop()
import math
print A, B, C, D, E, math.sqrt(169)  # prints 100 101 102 500 501 13.0

Seriously (and, yes, I'll attach enum.py anyway <wink>), while I generally
oppose by-hand counting too, you have to weigh it against the alternatives,
and anything else here is deadly obscure or deadly clumsy.  Not worth it.  I
usually don't bother to count correctly!  In this idiom, if you get the
count wrong Python will tell you by raising a "unpack of wrong size" error.
Most of the time you guess right; it's not worth any hassle to avoid the few
times you don't.

simple-code-for-our-simple-minds-ly y'rs  - tim


Here's enum.py.  Tutorees, reminder:  this is sick!  Sick, sick, sick.  Do
yourself a favor and don't look at it <wink>.

import __builtin__
_saved_import = __builtin__.__import__
_magic = "reset"
_nmagic = len(_magic)

def _hohoho(name, *args):
    global _base
    if name[:_nmagic] == _magic:
        _base = int(name[_nmagic:])
        return
    this = _base
    _base = _base + 1
    return this

def start(base=1):
    global _base
    _base = base
    __builtin__.__import__ = _hohoho

def stop():
    __builtin__.__import__ = _saved_import




From M.Faassen@vet.uu.nl  Wed Mar 31 08:18:25 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Wed, 31 Mar 1999 10:18:25 +0200
Subject: [Tutor] parsing chemical formula
References: <000a01be7b41$cee41f60$f19e2299@tim>
Message-ID: <3701DA50.6FC08574@pop.vet.uu.nl>

Tim Peters wrote:

> While I normally charge hefty royalties for use of this device, I hereby
> grant lifetime royalty-free licenses to all readers of the Tutor list
> <wink>.

Darn, I never paid royalties, where do I hide!

> You and Martijn went on to have a lot of fun making count-free variations,
> but you neglected to tell the tutorees that anything beyond this is *sick*
> fun.  Sick, sick, sick!  This is the way to do it:

Oh no, Christian, Timbot caught us!

[snip sick sick example costing way too many lines anyway]

> Seriously (and, yes, I'll attach enum.py anyway <wink>), while I generally
> oppose by-hand counting too, you have to weigh it against the alternatives,
> and anything else here is deadly obscure or deadly clumsy.  Not worth it. 

Agreed, still, this is of course an interesting challenge.

> I usually don't bother to count correctly!  In this idiom, if you get the
> count wrong Python will tell you by raising a "unpack of wrong size" error.
> Most of the time you guess right; it's not worth any hassle to avoid the few
> times you don't.

> simple-code-for-our-simple-minds-ly y'rs  - tim
> 
> Here's enum.py.  Tutorees, reminder:  this is sick!  Sick, sick, sick.  Do
> yourself a favor and don't look at it <wink>.
> 
[sick sick sick sick SICK code I don't pretend understanding deleted]

Regards,

Martijn


From M.Faassen@vet.uu.nl  Wed Mar 31 08:22:06 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Wed, 31 Mar 1999 10:22:06 +0200
Subject: [Tutor] chemical formula
References: <Pine.BSF.3.96.990330161536.15348A-100000@chemsun.chem.umn.edu>
Message-ID: <3701DB2E.A95F2DBC@pop.vet.uu.nl>

Tim Wilson wrote:
> If anyone knows of some
> reading I could do to get the "big picture" of OOP, please post it.

You might want to try this book; it doesn't mention Python but talks
about various OOP languages (the first edition which I read had C++,
Smalltalk, Object Pascal, Objective C, I believe, the newer apparantly
also includes Java and Delphi).

An Introduction to Object Oriented Programming (2nd Edition), Addison
Wesley, Reading, Massachusetts, 1997. 452pp.
ISBN 0-201-82419-1
by Timothy Budd

Regards,

Martijn


From alan.gauld@bt.com  Wed Mar 31 10:10:21 1999
From: alan.gauld@bt.com (alan.gauld@bt.com)
Date: Wed, 31 Mar 1999 11:10:21 +0100
Subject: [Tutor] chemical formula
Message-ID: <5104D4DBC598D211B5FE0000F8FE7EB24E08F0@mbtlipnt02.btlabs.bt.co.uk>

> understand it. I have yet to read a good tutorial on OOP for 
> the novice. 

Marginally off topic but I found Timothy Budd's OOP book excellent.
he uses several OOP languages to illustrate(Smalltalk, C++, Java, 
Delphi(OP) - I think they are) so you don't get hung up on a 
single languages view of OOP.

It explains the concepts well IMHO.

Alan G.


From StnCold180@aol.com  Wed Mar 31 18:31:11 1999
From: StnCold180@aol.com (StnCold180@aol.com)
Date: Wed, 31 Mar 1999 13:31:11 EST
Subject: [Tutor] programming
Message-ID: <61407840.370269ef@aol.com>

Hi. I am real interested in learning Python, but how do I go about starting?
What do I need? can you help?


Thanx,
John Akles (stncold180@aol.com)


From joe@strout.net  Wed Mar 31 18:45:26 1999
From: joe@strout.net (Joseph J. Strout)
Date: Wed, 31 Mar 1999 10:45:26 -0800
Subject: [Tutor] programming
In-Reply-To: <61407840.370269ef@aol.com>
Message-ID: <v04020a0bb3281d568bba@[198.202.70.213]>

>Hi. I am real interested in learning Python, but how do I go about starting?

Start with the Tutorial at:  http://www.python.org/doc/
It's marked "Start Here."  ;)

Then you might want to look at some simple scripts... here are a few:
	http://www.strout.net/python/tidbits.html

>What do I need?

You need a working installation of Python.  How exactly you get that
depends on what sort of computer you're using.

>can you help?

Yes, we can.  Ask us when you get stuck.

Cheers,
-- Joe

,------------------------------------------------------------------.
|    Joseph J. Strout           Biocomputing -- The Salk Institute |
|    joe@strout.net             http://www.strout.net              |
`------------------------------------------------------------------'


From M.Faassen@vet.uu.nl  Wed Mar 31 18:59:18 1999
From: M.Faassen@vet.uu.nl (Martijn Faassen)
Date: Wed, 31 Mar 1999 20:59:18 +0200
Subject: [Tutor] programming
References: <v04020a0bb3281d568bba@[198.202.70.213]>
Message-ID: <37027086.E0EB5089@pop.vet.uu.nl>

"Joseph J. Strout" wrote:
> 
> >Hi. I am real interested in learning Python, but how do I go about starting?
> 
> Start with the Tutorial at:  http://www.python.org/doc/
> It's marked "Start Here."  ;)

If you are new to programming and the tutorial confuses you, don't
worry; it's aimed at programmers coming from other languages primarily
(it is excellent for that). As Joe Strout said, just ask us here
whenever you get stuck or confused.

Regards,

Martijn