Tuesday, October 29, 2024

Teaching Myself Python, part 1

Right in the middle of my assembly language tutorial, I decided to teach myself Python.

(A friend needed some help with his classwork.)

I'm running the interactive interpreter, and this is a partial record of the conversation.

account@computer:~$ python
Python 2.7.17 (default, Sep 30 2024, 12:35:16) 
[GCC 7.5.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

That's pretty much not unexpected. 

What did I just do? 

I invoked Python with just 

python

at the bash shell command-line $ prompt. And Python tells me what version I'm running and some information about how it was built, followed by a prompt about things people might be particularly interested in. 

And you see I'm running a slightly old python -- version 2.7. (I actually have python v. 3 running, as well, but python v. 2 is my default right now.)

Where did I get Python?

Python gets installed by default now on a lot of Posix OSses. It's available in pretty much every distribution's package manager. I'm running an older version of Ubuntu Linux. (I need to upgrade, trying to decide between going back to Debian or over to Devuan, or staying with Ubuntu, or heading back to one of the BSDs.) 

I think v. 2 was installed by default, and I installed v. 3 from the packages. Or maybe it was the other way around, or maybe I installed both from packages. I don't remember.

If you're running MacOS, you can get Python from python.org or through one of several 3rd party package managers. (Macs actually come with Python, and it should be good enough for what I'm doing here. But if you decide to use Python regularly, it's recommended that you install a separate version so that you don't disturb the system's version when you install Python stuff that Mac OS doesn't use.)

If you're running MSWindows, you can apparently get Python from the Microsoft Store as well as from python.org. Or you can install Cygwin and get Python from the Cygwin packages.

And Python is available from python.org and others in the Android and Apple iOS stores, from what I hear.

Anyway, Python has been installed, and I have been putting off actually learning it, for quite a while. 

And there are two fundamental ways of running Python --

  1. Run a program written in Python (whether by clicking an icon or by invoking it at the command line), and
  2. run the interactive Python interpreter itself (whether by clicking an icon or invoking it at the command line)

I'm doing the latter, invoking it at the command line. (See above.)

What I type once Python is running is on the lines that start

>>>

Let's see what happens when I type "help", like the prompt suggests:

>>> help
Type help() for interactive help, or help(object) for help about object.
>>> 

Huh? 

Hmm. (Head scratching ensues.) 

Maybe, type "help()"?

>>> help()

Welcome to Python 2.7!  This is the online help utility.

If this is your first time using Python, you should definitely check out
the tutorial on the Internet at http://docs.python.org/2.7/tutorial/.

Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules.  To quit this help utility and
return to the interpreter, just type "quit".

To get a list of available modules, keywords, or topics, type "modules",
"keywords", or "topics".  Each module also comes with a one-line summary
of what it does; to list the modules whose summaries contain a given word
such as "spam", type "modules spam".

help>

And now it seems to be prompting me with "help> instead of ">>>".

Okay, "spam" sounds interesting.

help> spam
no Python documentation found for 'spam'

help>

Oh. I guess I need to type "modules spam" for that.

help> modules spam

Here is a list of matching modules.  Enter any module name to get more help.

Gtk-Message: 07:40:20.836: Failed to load module "canberra-gtk-module"

help>

I guess that means that something is not installed. I don't feel like chasing that down right now, so let's forget about the module "spam".

Maybe I could read up on arrays in Python.

help> modules array

Here is a list of matching modules.  Enter any module name to get more help.

array - This module defines an object type which can efficiently represent
numpy.core._methods - Array methods which are called by both the C-code for the method
numpy.core.arrayprint - Array printing function
numpy.core.defchararray - This module contains a set of functions for vectorized string
numpy.core.info - Defines a multi-dimensional array and useful procedures for Numerical computation.
numpy.core.multiarray 
numpy.core.multiarray_tests 
numpy.core.records - Record Arrays
numpy.lib.arraypad - The arraypad module contains a group of functions to pad values onto the edges
numpy.lib.arraysetops - Set operations for arrays based on sorting.
numpy.lib.arrayterator - A buffered iterator for big arrays.
numpy.lib.format - Define a simple format for saving numpy arrays to disk with the full
numpy.lib.mixins - Mixin classes for custom array types that don't inherit from ndarray.
numpy.lib.recfunctions - Collection of utilities to manipulate structured arrays.
numpy.lib.twodim_base - Basic functions for manipulating 2d arrays
numpy.lib.ufunclike - Module of functions that are like ufuncs in acting on arrays and optionally
numpy.lib.user_array - Standard container-class for easy multiple-inheritance.
numpy.ma.extras - Masked arrays add-ons.
numpy.ma.testutils - Miscellaneous functions for testing masked arrays and subclasses

help> 

Well, maybe I'll chase down the arrays module later and just get back to trying out Python. It said I could type "quit" to go back:

help> quit

You are now leaving help and returning to the Python interpreter.
If you want to ask for help on a particular object directly from the
interpreter, you can type "help(object)".  Executing "help('string')"
has the same effect as typing a particular string at the help> prompt.
>>> 

Well, that's useful information about how to use the help function.

Let's see if I can get Python to say "hello".

>>> hello
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'hello' is not defined
>>> 

Not that way. Maybe tell it to print it out?

>>> print hello
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'hello' is not defined
>>>

that doesn't seem to be the way to do it, either. I guess it needs to be quoted:

>>> print "hello"
hello
>>> 

That seems to work. What next?

>>> name = "Joel"
>>> print "hello ", name
hello  Joel
>>> 

Let's see if I can stroke my ego some more:

>>> rank = 1
>>> print "hello", name, "you're number ", rank, "!"
hello Joel you're number  1 !
>>> 

Cheap thrills. Heh.

One more vanity one-liner, but it requires putting either the program or the name in a file. We'll put the program in a file. 

To do this, you open up a text editor. Some people like geany or kate. I generally use gedit or vim. All four and others are available in most Posix OSses' package managers, and can be downloaded for Mac OS or installed via 3rd party package managers. 

Of course, Mac OS has Xcode (vim, too!), and I have found Xcode quite useful on Mac, useful enough that I usually have not installed gedit. (Make sure you download the command-line tools when you download Xcode.)

And, if you must use MSWindows, all four can be installed from Cygwin packages if you install Cygwin. (Geany and Gedit are supported for MSWindows, and can be downloaded from their respective download sites, but Kate takes a bit more work if you don't get it through Cygwin.) Or you can use Microsoft's Visual Studio. (Bleaugh. Just kidding. Sort-of.)

Anyway, open up a text editor and type in the following one-liner and save it in a directory called something like "play/python" as "greet.py". You'll need to change directory in your command-line shell, as well. Oh. Yeah. You'll need to use a command-line shell for this one. I don't think it can be done easily when you start Python by clicking an icon.

Actually, this one-liner is a two-liner:

import sys
print "Hello", sys.argv[ 1 ]

As I say, save it as "greet.py". Then go to your command-line shell and type the command "python greet.py Joel:

account@computer:~/play/python$ python greet.py Joel
Hello Joel
account@computer:~/play/python$ 

By way of explanation --

(1) You can save your program in a file with a ".py" extension (ending on the name) and have python run the program for you. Interactive is fun, but there are some things that don't work well interactively (can't work well interactively).

(2) Python makes whatever you type after the name of the program file available to your program in a list (I think it's a list.) called "argv", in the system module called "sys".

If you're not used to using these command-line parameters, that may not be much explanation, but once you start using them, they're not hard to understand.

Well, let's see what else might be interesting. Can I make the thing count?

>>> mylist = [ 1, 2, 3, 4 ]
>>> print mylist, "I just plain adore ..."
[1, 2, 3, 4] I just plain adore ...
>>> 

Rim shot. Let's try an explicit loop:

>>> for i in range( 1, 4 )
  File "<stdin>", line 1
    for i in range( 1, 4 )
                         ^
SyntaxError: invalid syntax
>>> 

Ooooh, rejected!

Needs a colon on the end. Try again:

>>> for i in range( 1, 4 ):
...   print i
... 
1
2
3
>>> 

The "..." ellipsis prompt means it wants you to type more. So I typed the body of the loop.

And it's still not quite there. The last number in the range is not included.

Point one, for people who like their code blocks to have beginning braces and end braces or BEGIN and END keywords, Python uses indentation to demarcate blocks.

Yeah. The whitespace. The stuff you've trained yourself to not see. Or at least I have.

That's one of the reasons I got miffed at Python in the past. But I have a friend this time, so I'll just go with it.

I do see that the colon seems to be a sort of BEGIN marker. And after some playing around late last night, I figured out that, even though python doesn't require it, you can put comment characters in place to show where the indentation hits. It's kind of like painting the fingers of your invisible robot hands so you can see what they're doing, but it seems to sort of do the job.

My friend needs help with working through a list, summing up a column, and taking an average. So let's look at two ways to sum a list in Python. This is a kind of a sudden jump, but we've seen most of the essential elements of the language that I'm using, so, hang on to your hat, and I'll hang on to mine:

Grabbing input from the keyboard can get confusing, so we're gong to save this as a program, call it "totaloop.py":

total = 0
count = 0
for i in range( 1, 10):
  numstr = input()
  previous = total
  total = total + numstr
  count = count + 1
  print count, ": ", previous, " + ", numstr, " = ", total ;
  # end of loop

average = float( total ) / count
print "average of ", total, " / ", count, " is ", average

What this does is

  • read a number from the keyboard,
  • add it immediately to the total, and
  • print out the number, count, and running total
  • until 9 numbers have been read; 
  • at which point, the average is calculated and printed out.

Make sure you save it with the empty trailing line. Call it from the command line, like this:

$ python totaloop.py

And then type in a bunch of numbers

$ python totaloop.py
2
1 :  0  +  2  =  2
6
2 :  2  +  6  =  8
3
3 :  8  +  3  =  11
2
4 :  11  +  2  =  13
3
5 :  13  +  3  =  16
6
6 :  16  +  6  =  22
4
7 :  22  +  4  =  26
9
8 :  26  +  9  =  35
3
9 :  35  +  3  =  38
average of  38  /  9  is  4.22222222222

You can see that I typed in the numbers 2 6 3 2 3 6 4 9 3.

Now, instead of immediately calculating the running total, we'll input the entire list first, and then use a built-in function to sum up the whole list:

numbers = []
for i in range( 1, 10 ):
  numstr = input()
  numbers.append( float( numstr ) )
  print i, ": ", numstr, numbers 
  # End of loop

total = sum( numbers )
average = total / len( numbers )

print "list: ", numbers
print "sum is ", total, " and average is ", average

Re-emphasizing, the program 

  • reads in a number,
  • appends it to the list,
  • prints the number read and the list
  • until 9 numbers are read,
  • and then, after the loop is finished, sums them all up and
  • prints the results 

Call it from the command line and type in the list of numbers typed in before just so we can compare:

$ python totalist.py
2
1 :  2 [2.0]
6
2 :  6 [2.0, 6.0]
3
3 :  3 [2.0, 6.0, 3.0]
2
4 :  2 [2.0, 6.0, 3.0, 2.0]
3
5 :  3 [2.0, 6.0, 3.0, 2.0, 3.0]
6
6 :  6 [2.0, 6.0, 3.0, 2.0, 3.0, 6.0]
4
7 :  4 [2.0, 6.0, 3.0, 2.0, 3.0, 6.0, 4.0]
9
8 :  9 [2.0, 6.0, 3.0, 2.0, 3.0, 6.0, 4.0, 9.0]
3
9 :  3 [2.0, 6.0, 3.0, 2.0, 3.0, 6.0, 4.0, 9.0, 3.0]
list:  [2.0, 6.0, 3.0, 2.0, 3.0, 6.0, 4.0, 9.0, 3.0]
sum is  38.0  and average is  4.22222222222

The first way uses less memory.

The second way is what you use if you need to do more than one thing with the list of numbers.

Let's say you want to remember what the 4th number entered was and print it out at the end. 

You could add code to the first one like this:

total = 0
count = 0
memo = 0
for i in range( 1, 10):
  numstr = input()
  previous = total
  total = total + numstr
  count = count + 1
  if count == 4:
    memo = numstr
    # end of conditional
  print count, ": ", previous, " + ", numstr, " = ", total ;
  # end of loop

average = float( total ) / count
print "average of ", total, " / ", count, " is ", average
print "4th number:", memo

Essentially, watch the count, and when it hits 4 put the input number in the memo variable.

Note that Python wants an empty line at the same indentation at the end of the loop and at the end of the conditional if. I'm marking the empty line and the indentation with a comment. (Comments have no code, and can serve as empty lines.)

If you fail to indent the trailing empty line, it terminates everything (and makes a fuss about syntax).

Here's a way we can do it if we keep the whole list in memory:

numbers = []
for i in range( 1, 10 ):
  numstr = input()
  numbers.append( float( numstr ) )
  print i, ": ", numstr, numbers 
  # End of loop

total = sum( numbers )
average = total / len( numbers )

print "list: ", numbers
print "sum is ", total, " and average is ", average
# first is numbers[ 0 ], 4th is numbers[ 3 ]
print "4th number:", numbers[ 3 ]

Since we still have the whole list in memory, we can just index the 4th element. Remember, lists start with index 0, so the first one is numbers[0]. Therefore, the 4th one is at index 3, numbers[3].

Hopefully, this will be enough for my friend to work it through.

No comments:

Post a Comment