Python Slides, 1997

Python Talk Material (1997)

[Note from the future: this page was restyled in 2018 for mobile, but its original content was left intact (even the silly bits). Early days to be sure, but most of it is still surprisingly relevant two decades later. The talk announcement is still online

here

, while it

lasts

.]

This page contains HTML renditions of slides from an introductory talk on Python I've given in the past. Some of it has been updated, but not since its last change date: 5/23/97.

Much of this material comes from the book "Programming Python". Since the pages here lack the narrative you'd get in a talk (or the book), I'm not sure how useful this is as an intro to Python; on the other hand, it's free :-).

Please send comments about this page to

[email protected]

.

Contents

Talk outline

But first: the book plug...

I. General Overview

So what's Python?

Major features

Some quotable quotes

A more formal definition

The Life Of Python

What's Python good for?

What's Python not good for?

The Compulsory Features List

Python Portability

General portability

Platform Extensions

Major Python Packages

Python in the "Real World"

On Bananas and Coconuts

II. Python Resources

Internet Resources

Python Books

Recent Python Articles

PSA-sponsored Python Conferences

Python Training

III. A first look at the language

How to Run Python Programs

Builtin object types

Numbers

Strings

Lists

Dictionaries

Tuples

Files

And everything else...

General properties

Basic statements

Simple statements

Compound statements

Program unit statements

Functions

Modules

Classes

Exceptions

A pragmatic interlude: system interfaces

OOP and inheritance

OOP and composition

Functions are objects: indirect calls

Classes are objects: factories

Methods are objects: bound or unbound

Modules are objects: metaprograms

Python/C integration

Summary: Python tool-set layers

IV. Real Python Programs

Simple shell tools

GUI programming

Persistent Python objects

Fun with Sets

The Python FTP module

Sockets in Python

Text processing: regular expressions

Text processing: splitting files by columns

System interfaces: regression tests

Other things that weren't covered

Also see the

appendix page

for supplemental material. Some of it is specific to a company I've worked for, but it also includes some general Python information not listed above:

Running Python

Extending Python in C/C++

Embedding Python in C/C++

Update: also see the new

integration examples page

for more Python/C integration examples.

———
"And now, for something completely different..." Mark Lutz March 1997
———

Talk outline

A high-level overview of Python

Pointers to Python resources

A first look at the language

Real Python programs (as time allows)

———

But first: the book plug...

[O'Reilly book cover]
[O'Reilly book cover]

A "Tour" of Python: language, tools, OOP, C/C++ integration

Coming soon: Japanese language edition

Currently in second printing (minor typo fixes only)

O'Reilly's

description

———

———

I. General Overview

Definitions

Features

Common Roles

History

Plus lots of hand-waving

———

———

So what's Python?

An object-oriented scripting language

A stand-alone rapid development tool

A "next-generation extension language"

A freely available, interpreted language

In acronyms: VHLL, OODL

Major features

Support for object-oriented development

Powerful programming constructs

Extendible and embeddable architecture

Remarkably clear syntax and coherent design

Some quotable quotes

"Python looks like it was designed, not accumulated."

"It bridges the gap between scripting languages and C."

"Python is the BASIC of the 90's."

"As easy or as powerful as you want it to be."

"Python: Less Filling, Tastes Great." :-)

A more formal definition

Seen on comp.lang.python...

"python, (Gr. Myth. An enormous serpent that lurked in the cave of Mount Parnassus and was slain by Apollo) 1. any of a genus of large, non-poisonous snakes of Asia, Africa and Australia that crush their prey to death. 2. popularly, any large snake that crushes its prey. 3. totally awesome, bitchin' language invented by that rad computer geek Guido van Rossum that will someday crush the $'s out of certain *other* so-called VHLLs ;-)"

———

The Life Of Python

Created by Guido van Rossum in Amsterdam, 1990

Named after "Monty Python's Flying Circus"

Python Software Activity (PSA), hosted by CNRI

International following: Europe, Japan, Australia, US

What's Python good for?

System administration
System tools: sockets, regex, POSIX

Graphical user interfaces
Tk, MFC, X11

Internet scripting
CGI, applets, agents, crawlers

Database programming
Persistence, Oracle, Informix, Sybase,...

Component integration
Embedded scripting tools, system front-ends

Rapid Application Development
Prototype-and-migrate, fast turnaround

And more
Numeric programming, AI, graphics, CORBA,...

What's Python

not good for?

Time-critical components

Solution: implement in C/C++ and export to Python!

Optimized for speed-of-development

Designed for multi-language systems

Example: Python Numeric Programming: Python + extensions

The Compulsory Features List

No compile or link steps
Rapid development-cycle turnaround

No type declarations
Programs are simpler, shorter, and flexible

Automatic memory management
Garbage collection avoids book-keeping code

High-level datatypes and operations
Fast development using built-in object types

Object-oriented programming
Code structuring and reuse, C++ integration

Extending and embedding in C
C integration, mixed-language systems

Classes, modules, exceptions
Modular 'programming-in-the-large' support

Dynamic loading of C modules
Simplified extensions, smaller binary files

Dynamic reloading of Python modules
Programs can be modified without stopping

Universal "first-class" object model
Fewer restrictions and special-case rules

Interactive, dynamic nature
Incremental testing, runtime program construction

Access to interpreter information
Metaprogramming, introspective objects

Wide portability
Cross-platform systems

Compilation to portable byte-code
Execution speed, protecting source-code

Built-in interfaces to external services
O/S, GUI, object persistence, DBMS, regular expressions...

True "freeware": source code available on the net
Can be freely shipped/embedded, no copyright restrictions

———

Python Portability

UNIX (and Linux)

Windows 3.1, 95, NT

MS-DOS

Macintosh

OS/2

VMS

Next

Be OS

Amiga, Atari ST

And others

General portability

Compiled to portable byte-code (on import)

Tkinter GUI API: runs on X11, MS-Windows, Macs

Platform Extensions

PythonWin: ActiveX, MFC, COM, IDE, DLLs

MacPython: PPC, 68K, AppleEvents

The PythonWin IDE

[PythonWin IDE]
[PythonWin IDE]

Major Python Packages

Netscape plugins

Tkinter: Tk GUI API (OO)

WPY: portable GUI API

PIL: imaging library

ILU: distributed objects (CORBA)

SWIG: C/C++ wrapper generator

Numeric Python

A first look: the Grail web browser in action

Written entirely in Python (portable)

Uses Tkinter as the browser GUI API (portable)

Client browser downloads and runs applets referenced in HTML

Python also supports server-side CGI scripts, FTP, ActiveX, etc.

HTML file <HEAD> <TITLE>Grail Applet Test Page</TITLE> </HEAD> <BODY> <H1>Test an Applet Here!</H1> Click this button! <APP CLASS=Question> </BODY> file: Question.py # Python applet file: Question.py # in the same location (URL) as the html file # that references it; adds widgets to browser; from Tkinter import * class Question: # run by grail? def __init__(self, master): # master=browser self.button = Button(master, bitmap='question', command=self.action) self.button.pack() def action(self): if self.button['bitmap'] == 'question': self.button.config(bitmap='questhead') else: self.button.config(bitmap='question') if __name__ == '__main__': root = Tk() # run stand-alone? button = Question(root) # master=Tk: top-level root.mainloop()

[Grail web browser]
[Grail web browser]

WPY at work

WPY: MFC-like class library for MS-Windows and UNIX

Example: the 'Scribble" MSVC++ demo in Python

PythonWin provides more Windows-specific tools

Tkinter also runs on Windows (plus Macs, X)

[Scribble under WPY]
[Scribble under WPY]

———

Python in the "Real World"

Surfing made easy (Infoseek, Four11)

Cockroaches and Pepsi Jingles (Blue Sky animation)

Blowing up the energizer bunny (Alice VR)

Rocket Science (Lawrence Livermore, NASA)

Distributed object systems (Hector, ILU)

ActiveX scripting (various)

Linux install tools (Red Hat)

Finding the Grail (CNRI, intelligent agents)

On Bananas and Coconuts

Python versus...

Tcl
Power: not just a string processor--modules, OOP

Perl
Coherence: readability, maintainability, less magic

Java
Simplicity: builtin tools, dynamic typing, object model

C++
Turnaround: interpreted, simpler, more dynamic

Smalltalk
Conventional: "if" statements are not objects

But YMMV!

Programmers matter too

Many languages are a Good Thing

———

———

II. Python Resources

The Internet

Books

Articles

Conferences

Training

———

———

Internet Resources

Python's website

www.python.org

My website

starship.python.net/~lutz.home

O'Reilly's website

www.ora.com

Python's FTP site

ftp.python.org

Python's general USENET newsgroup (and mail-list)

comp.lang.python

Python's technical help/support mail-list

[email protected]

CompuServe Python forum
go python

German-language email list

Python Books

"Programming Python", O'Reilly & Associates

"Internet Programming with Python", MIS Press

"Das Python-Buch", Addison Wesley (German)

Fall '97: "Instant Python Applications"?, O'Reilly

Fall '97: "Programming Python", Japanese language edition

And others still in the rumor stage: Python/Windows, etc.

Also useful

Python's standard reference manuals

Python library modules and demos

"The Fairly Incomplete & Rather Badly Illustrated Monty Python Song Book", HarperCollins

Recent Python Articles

Linux Journal, May: Python Update

World Wide Web Journal, April: Scripting Languages

BYTE, February: Core Technologies section

Linux Journal, February: Python CGI programming

Web Review, January 3 (http://webreview.com)

Dr. Dobbs Sourcebook, January/February: Hector, ILU

(Upcoming) Chapter in Handbook of Object Technologies

(Upcoming) Chapter in Programming Languages Handbook

(Upcoming) Series in Japanese Dr. Dobbs

PSA-sponsored Python Conferences

Bi-annual gatherings: see www.python.org

6th International Python

Conference

: October '97, San Jose

Python Training

Digital Creations seminars and training

See

mytrain.html

———

———

III. A first look at the language

Builtin object types

Basic statements

Program Structure

Python's OOP model

C integration and RAD

Plus lots of small, artificial examples

———

———

How to Run Python Programs

UNIX scripts

file: brian.py #!/usr/local/bin/python print 'The Bright Side of Life...' % brian.py Module Files

% python spam.py -i eggs -o bacon Interactive command line

% python >>> print 'Hello world!' Hello world! >>> lumberjack = "okay" Embedded Code/Objects

Py_Initialize(); PyRun_SimpleString("x = brave + sir + robin"); Notes: on UNIX, the environment variable PYTHONPATH should list all source directories you want to import modules from. Program start techniques and configuration details differ on Windows and Macintosh platforms; see package documentation.

———

Builtin object types

Numbers: 3.1415 Strings: 'spam' Lists: [1, [2, 'three']] Dictionaries: {'food':'spam', 'taste':'yum'} Tuples: (1,'spam', 4, 'U') Files: open('temp', 'r').read()

Numbers

Common operations

1234 normal integers (C long's) 99999999L long integers (unlimited size) 1.23, 3.14e-10 floating-point (C double's) 0177, 0x9ff octal and hex constants Interactive examples

% python >>> a = 3 >>> b = 4 >>> b / 2 + a 5 >>> b / (2.0 + a) 0.8 >>> 9999999999999999999999999999 + 1 OverflowError: integer literal too large >>> 9999999999999999999999999999L + 1 10000000000000000000000000000L

Strings

Common operations

s1 = '' empty strings s2 = "spam's" double quotes s2[i], s2[i:j] indexing, slicing s1 + s2, s2 * 3 concatenate, repeat "a %s parrot" % 'dead' string formatting block = """...""" triple-quoted blocks Interactive examples

% python >>> 'abc' + 'def' 'abcdef' >>> 'Ni!' * 4 # like "Ni!" + "Ni!" + ... 'Ni!Ni!Ni!Ni!' >>> S = 'spam' >>> S[0], S[-2] # same as: S[len(S)-2] ('s', 'a') >>> S[:-1], S[1:] ('spa', 'pam') >>> 'That is %d %s bird!' % (1, 'dead') That is 1 dead bird!

Lists

Common operations

L1 = [] an empty list L2 = [0, 1, 2, 3] 4-items: indexes 0..3 ['abc', ['def', 'ghi']] nested sublists L2[i], L2[i:j] indexing, slicing L1 + L2, L2 * 3 concatenate, repeat L2.append(newvalue) growing: methods del L2[k], L2[i:j] = [] shrinking L2[i:j] = [1,2,3] slice assignment range(4), xrange(0, 4) make integer lists Interactive examples

% python >>> [1, 2, 3] + [4, 5, 6] [1, 2, 3, 4, 5, 6] >>> ['Ni!'] * 4 ['Ni!', 'Ni!', 'Ni!', 'Ni!'] >>> L = ['spam', 'Spam', 'SPAM!'] >>> L[2] 'SPAM!' >>> L[1] = 'eggs' >>> for x in L: print x, ... spam eggs SPAM!

Dictionaries

Common operations

d1 = {} empty d2 = {'spam': 2, 'ham': 1, 'eggs': 3} 3-items d3 = {'pork': {'ham': 1, 'brats': 2}} nesting d2['eggs'], d3['pork']['ham'] indexing d2.has_key('eggs'), d2.keys() methods Interactive examples

% python >>> table ={'Perl': 'Larry Wall', ... 'Tcl': 'John Ousterhout', ... 'Python': 'Guido van Rossum' } ... >>> language = 'Python' >>> creator = table[language] 'Guido van Rossum'

Tuples

Common operations

() an empty tuple t1 = (0,) a one-item tuple t2 = (0, 1, 2, 3) 4-item tuple t3 = ('abc', ('def', 'ghi')) nested tuples t1[i], t1[i:j] index, slice t1 + t2, t2 * 3 concatenate, repeat

Files

Common operations

o = open("/tmp/spam", 'w') output file i = open('data', 'r') input file i.read(), i.readline(), i.read(1) file,line,char o.write(s), o.writelines(l) string,lines o.close() or when free'd

And everything else...

In Python, everything is an object type.

Functions

Modules

Methods

Classes

Byte-compiled code

Stack tracebacks

General properties

Heterogeneous

Nestable

Shared object references

Dynamically resizable (most)

Operation categories: sequence, mapping, number

Nesting example

L = ['abc', [(1,2), ([3], 4)], 5]

[Nested data structures]
[Nested data structures]

———

Basic statements

Python syntax...

No braces or semicolons

The "what you see is what you get" of languages

No variable/type declarations

Python assignment...

Assignments create object references

Variables are created when first assigned

Variables must be assigned before being referenced

Python programming...

Modules are automatically compiled when imported

Program comments start with a "#"

Debugger and profiler are imported modules

———

Simple statements

Assignment

spam = 'SPAM' basic form spam, ham = 'yum', 'YUM' tuple assignment [spam, ham] = ['yum', 'YUM'] list assignment spam = ham = 'lunch' multi-target Expressions

spam(egs, ham) function calls spam.ham(eggs) method calls spam print interactive spam < ham and ham != eggs compound expr's spam < ham < eggs range tests Print

print spam, ham print objects to sys.stdout print spam, ham, don't add linefeed
———

Compound statements

If selections

>>> x = 'killer rabbit' >>> if x == 'bunny': ... print 'hello little bunny' ... elif x == 'bugs': ... print "what's up doc?" ... else: ... print 'Run away! Run away!...' ... Run away! Run away!... While loops

while 1: print 'Type Ctrl-C to stop me!' The loop "else"... x = y / 2 while x > 1: if y % x == 0: # remainder print y, 'has factor', x break # skip else x = x-1 else: # normal exit print y, 'is prime' For loops

>>> for x in ["spam", "eggs", "spam"]: ... print x, ... spam eggs spam Counter loops... >>> range(5) [0, 1, 2, 3, 4] >>> for i in xrange(len(X)): print X[i] >>> for i in range(5): print 'A shrubbery!' ... A shrubbery! A shrubbery! A shrubbery! A shrubbery! A shrubbery!
———

Program unit statements

Modules: code/data packages Classes: new objects Functions: procedural units C modules: optimization, integration Exceptions: errors and special cases Modules contain Statements that process Objects

[Module relationships]
[Module relationships]

———

Functions

"def" creates a function object

Arguments are passed by object reference

Assignments create local names unless "global X"

References search 3 scopes: local, global, builtin

"lambda" creates anonymous functions

Keyword arguments, varargs, defaults

def intersect(seq1, seq2): res = [] # start empty for x in seq1: # scan seq1 if x in seq2: # common item? res.append(x) # add to end return res >>> s1 = "SPAM" >>> s2 = "SCAM" >>> intersect(s1, s2) # strings ['S', 'A', 'M'] >>> intersect([1, 2, 3], (1, 4)) # mixed types [1]

Modules

Form: Python files or C extensions

Usage: "import", "from", "reload()"

Module search path: $PYTHONPATH

__main__ and __name__

Compiled modules: .pyc

Everything lives in a module

file: hello.py def printer(x): print x % python >>> import hello >>> hello.printer('Hello world!') Hello world! >>> from hello import printer >>> printer('Hello world!') >>> from hello import * >>> printer('Hello world!')

Classes

"class" creates a class object

Calling a class creates an instance

Instances inherit attributes from classes

Classes inherit attributes from superclasses

Methods are nested functions with a 'self'

class FirstClass: # class def printer(self, text): # method print text x = FirstClass() x.printer('Hello world!') class SecondClass(FirstClass): # subclass def __init__(self, value): # constructor self.name = value def printname(self): self.printer(self.name) # inherited x = SecondClass('Hello world!') x.printname() More on Python's OOP model

Members are created when assigned

Methods are all 'public' and 'virtual'

Multiple inheritance: class X(Y, Z)

Operator overloading, metaclass protocols: __X__

class Counter: def __init__(self, start): # on Counter() self.data = start def __call__(self): # on x() self.data = self.data + 1 return self.data def __add__(self, y): # on x + y return Counter(self.data + y) def __repr__(self): # on print return `self.data` if __name__ == "__main__": x = Counter(2) # self-test x = x + 4 print x # 6 c1 = Counter(10) c2 = Counter(24) print c1(), c2(), c1(), c2() # 11, 25, 12, 26

Exceptions

"try" statements catch exceptions

"raise" statements trigger exceptions

Python triggers builtin exceptions

User-defined exceptions are objects

Builtin exceptions... def kaboom(list, n): print list[n] # trigger IndexError try: kaboom([0, 1, 2], 3) except IndexError: print 'Hello world!' # catch exception here User-defined exceptions... MyError = "my error" def stuff(file): raise MyError file = open('data', 'r') # open a file try: stuff(file) # raises exception finally: file.close() # always close file

———

A pragmatic interlude: system interfaces

Python tools: sys

>>> import sys >>> sys.path ['.', '/usr/local/lib/python', ... ] >>> sys.platform 'sunos4' System tools: os

>>> import os >>> os.environ['USER'] 'mlutz' >>> listing = os.popen("ls *.py").readlines() >>> for name in listing: print name, ... cheader1.py finder1.py summer.py >>> for name in listing: os.system("vi " + name) ... >>> os.listdir(".") ['summer.out', 'summer.py', 'table1.txt', ... ] File globbing: glob, string

>>> import glob, string, os >>> glob.glob("*.py") ['cheader1.py', 'finder1.py', 'summer.py'] >>> for name in glob.glob("*.py"): ... os.rename(name, string.upper(name)) ... >>> glob.glob("*.PY") ['FINDER1.PY', 'SUMMER.PY', 'CHEADER1.PY'] Arguments and streams: sys

% cat play.py #!/usr/local/bin/python import sys print sys.argv sys.stdout.write("ta da!\n") % play.py -x -i spammify ['play.py', '-x', '-i', 'spammify'] ta da!

———

OOP and inheritance

A zoo-animal hiearchy in Python

file: zoo.py class Animal: def reply(self): self.speak() def speak(self): print 'spam' class Mammal(Animal): def speak(self): print 'huh?' class Cat(Mammal): def speak(self): print 'meow' class Dog(Mammal): def speak(self): print 'bark' class Primate(Mammal): def speak(self): print 'Hello world!' class Hacker(Primate): pass % python >>> from zoo import Cat, Hacker >>> spot = Cat() >>> spot.reply() meow >>> data = Hacker() >>> data.reply() Hello world!

[Zoo animal hierarchy]
[Zoo animal hierarchy]

OOP and composition

The dead-parrot skit in Python

file: parrot.py class Actor: def line(self): print self.name + ':', `self.says()` class Customer(Actor): name = 'customer' def says(self): return "that's one ex-bird!" class Clerk(Actor): name = 'clerk' def says(self): return "no it isn't..." class Parrot(Actor): name = 'parrot' def says(self): return None class Scene: def __init__(self): self.clerk = Clerk() # embed some instances self.customer = Customer() # Scene is a composite self.subject = Parrot() def action(self): self.customer.line() # delegate to embedded self.clerk.line() self.subject.line() % python >>> import parrot >>> parrot.Scene().action() customer: "that's one ex-bird!" clerk: "no it isn't..." parrot: None

[Dead parrot skit]
[Dead parrot skit]

———

Functions are objects: indirect calls

def echo(message): print message x = echo x('Hello world!') def indirect(func, arg): func(arg) indirect(echo, 'Hello world!') schedule = [ (echo, 'Hello!'), (echo, 'Ni!') ] for (func, arg) in schedule: apply(func, (arg,)) File scanners

file: scanfile.py def scanner(name, function): file = open(name, 'r') # create file for line in file.readlines(): function(line) # call function file.close() file: commands.py import string from scanfile import scanner def processLine(line): print string.upper(line) scanner("data.txt", processLine) # start scanner

Classes are objects: factories

def factory(aClass, *args): # varargs tuple return apply(aClass, args) # call aClass class Spam: def doit(self, message): print message class Person: def __init__(self, name, job): self.name = name self.job = job object1 = factory(Spam) object2 = factory(Person, "Guido", "guru")

Methods are objects: bound or unbound

x = object1.doit # bound method object x('hello world') # instance is implied t = Spam.doit # unbound method object t(object1, 'howdy') # pass in instance

Modules are objects: metaprograms

file: fixer.py editor = 'vi' # your editor's name def python(cmd): import __main__ namespace = __main__.__dict__ exec cmd in namespace, namespace def edit(filename): import os os.system(editor + ' ' + filename) def fix(modname): import sys # edit,(re)load edit(modname + '.py') if modname in sys.modules.keys(): python('reload(' + modname + ')') else: python('import ' + modname) % python >>> from fixer import fix >>> fix("spam") # browse/edit and import by string name >>> spam.function() # spam was imported in __main__ >>> fix("spam") # edit and reload() by string name >>> spam.function() # test new version of function

———

Python/C integration

[See the

appendix

for examples]

Extending Python in C

For optimization, integration

C Extension Modules

C Extension Types

Wrapper Classes

Automated Tools: SWIG, ILU

Embedding Python in C

For dynamic application extensions

Strings

Objects

Methods

Modules and scripts

Going both ways

Python and rapid development

The RAD slider: Python <==> C/C++

Prototype-and-migrate

Move selected Python modules to C/C++

C modules look just like Python modules

C types look almost like Python classes

Hybrid designs

———

Summary: Python tool-set layers

Builtins: lists, dictionaries, strings, etc.
High-level tools for simple, fast programming

Python extensions: functions, classes, modules
Adding extra features, and new object types

C extensions: C modules, C types
Integrating external systems, optimizing components

———

———

IV. Real Python Programs

Shell tools

Data-structure classes

Graphical user interfaces

Persistent objects

Text processing

Plus lots of big, confusing examples

———

———

Simple shell tools

Packing files with simple scripts

The !# trick: executable modules

Command-line arguments

Standard input/output streams

% cat packer.py #!/usr/local/bin/python import sys # load the system module marker = '::::::' for name in sys.argv[1:]: # for all command-line args input = open(name, 'r') # open the next input file print marker + name # write a separator line print input.read(), # write the file's contents % packer.py spam.txt eggs.txt toast.txt > packed.txt Packing files with a class framework

Inherits start/run/stop method protocol

Redefines start, run, and help locally

System interfaces wrapped: streams, arguments, etc.

% cat packapp.py #!/usr/local/bin/python from apptools import StreamApp # get the superclass from textpack import marker # get marker constant class PackApp(StreamApp): # define a subclass def start(self): # define some methods if not self.args: self.exit('packapp.py [-o file]? src src...') def help(self): StreamApp.help(self) # superclass args print '<file> <file>...' # then show my args def run(self): for name in self.restargs(): try: self.message('packing: ' + name) self.pack_file(name) except: self.exit('error processing: ' + name) def pack_file(self, name): self.setInput(name) self.write(marker + name + '\n') while 1: line = self.readline() # read next line if not line: break # until eof self.write(line) # copy to output if __name__ == '__main__': PackApp().main() # script? % packapp.py -o packed.txt spam.txt eggs.txt toast.txt

———

GUI programming

Tkinter: an OO interface to Tk

Import classes and make instances

Configuration options: keyword arguments

Build GUIs by subclassing and embedding

Portable to X-Windows, MS-Windows, Macs

file: hello #!/usr/local/bin/python from Tkinter import * # get widget classes class Hello(Frame): # container subclass def __init__(self, parent=None): Frame.__init__(self, parent) # do superclass init self.pack() self.make_widgets() def make_widgets(self): widget = Button(self, text='Hello world', command = self.onPress) widget.pack(side=LEFT) def onPress(self): print "Hi." if __name__ == '__main__': Hello().mainloop() % hello

———

Persistent Python objects

Shelve = DBM (keyed file) + Pickling (serialization)

Exports dictionary-like interface

Shelves can store arbitrary Python objects

Pickles without shelves

Changing classes changes stored object behavior

file: person.py # a person object: fields + behavior # class defined at outer level of file class Person: def __init__(self, name = '', job = '', pay = 0): self.name = name self.job = job self.pay = pay # real instance data def tax(self): return self.pay * 0.25 # computed on demand def info(self): return self.name, self.job, self.pay, self.tax() % python >>>jerry = Person('jerry', 'dentist') >>>bob = Person('bob', 'psychologist', 70000) >>>emily = Person('emily', 'teacher', 40000) ... >>>import shelve >>>dbase = shelve.open('cast') # open a new dbm file >>>for obj in (bob, emily, jerry): # put objs in a shelve >>> dbase[obj.name] = obj ... >>>import shelve >>>dbase = shelve.open('cast') # reopen shelve file >>>print dbase['bob'].info() # fetch 'bob' object

———

Fun with Sets

Using functions

Using classes

Extensions: multiple operands, dictionaries

Set functions

file: inter.py def intersect(list1, list2): res = [] # start with an empty list for x in list1: # scan the first list if x in list2: res.append(x) # add common items to end return res def union(list1, list2): res = map(None, list1) # make a copy of list1 for x in list2: # add new items in list2 if not x in res: res.append(x) return res % python >>> from inter import * >>> s1 = "SPAM" >>> s2 = "SCAM" >>> intersect(s1, s2), union(s1, s2) # strings (['S', 'A', 'M'], ['S', 'P', 'A', 'M', 'C']) >>> intersect([1,2,3], (1,4)) # mixed types [1] >>> union([1,2,3], (1,4)) [1, 2, 3, 4] Set classes

file: set.py class Set: def __init__(self, value = []): # constructor self.data = [] # manages a list self.concat(value) def intersect(self, other): # other is a sequence res = [] # self is the subject for x in self.data: if x in other: res.append(x) return Set(res) # return a new Set def union(self, other): res = self.data[:] # copy of my list for x in other: if not x in res: res.append(x) return Set(res) def concat(self, value): # value: list, Set... for x in value: # removes duplicates if not x in self.data: self.data.append(x) def __len__(self): return len(self.data) def __getitem__(self, key): return self.data[key] def __and__(self, other): return self.intersect(other) def __or__(self, other): return self.union(other) def __repr__(self): return 'Set:' + `self.data` % python >>> from set import Set >>> x = Set([1,2,3,4]) # __init__ >>> y = Set([3,4,5]) >>> x & y, x | y # __and__,__or__,__repr__ (Set:[3, 4], Set:[1, 2, 3, 4, 5]) >>> z = Set("hello") # set of strings >>> z[0] # __getitem__ 'h' >>> z & "mello", z | "mello" (Set:['e', 'l', 'o'], Set:['h', 'e', 'l', 'o', 'm']) Multiple operands: *varargs

file: inter2.py def intersect(*args): res = [] for x in args[0]: # scan first list for other in args[1:]: # for all other args if x not in other: break # this in each one? else: res.append(x) # add items to end return res def union(*args): res = [] for seq in args: # for all args for x in seq: # for all nodes if not x in res: res.append(x) # add items to result return res % python >>> from inter2 import * >>> s1, s2, s3 = "SPAM", "SCAM", "SLAM" >>> intersect(s1, s2), union(s1, s2) # 2 operands (['S', 'A', 'M'], ['S', 'P', 'A', 'M', 'C']) >>> intersect([1,2,3], (1,4)) [1] >>> intersect(s1, s2, s3) # 3 operands ['S', 'A', 'M'] >>> union(s1, s2, s3) ['S', 'P', 'A', 'M', 'C', 'L']

———

The Python FTP module

#!/usr/local/bin/python ############################################### # Usage: % sousa.py # Fetch and play the Monty Python theme song. ############################################### import os, sys from ftplib import FTP # socket-based ftp tools from posixpath import exists # file existence test sample = 'sousa.au' filter = {'sunos5': '/usr/bin/audioplay', 'linux1': '', 'sunos4': '/usr/demo/SOUND/play'} helpmsg = """ Sorry: can't find an audio filter for your system! Add an entry to the script's "filter" dictionary for your system's audio command, or ftp and play manually. """ # check the filter if (filter.has_key(sys.platform) and exists(filter[sys.platform])): print 'Working...' else: print helpmsg sys.exit(1) # ftp the audio file if not exists(sample): theme = open(sample, 'w') ftp = FTP('ftp.python.org') # connect to ftp site ftp.login() # use anonymous login ftp.cwd('pub/python/misc') ftp.retrbinary('RETR ' + sample, theme.write, 1024) ftp.quit() theme.close() # send it to audio device theme = open(sample, 'r') audio = os.popen(filter[sys.platform], 'w') # spawn tool audio.write(theme.read()) # to stdin

———

Sockets in Python

Imported socket module

Socket objects with methods

file: sockserver.py # Echo server program from socket import * HOST = '' # the local host PORT = 50007 # non-privileged server s = socket(AF_INET, SOCK_STREAM) s.bind(HOST, PORT) s.listen(1) conn, addr = s.accept() print 'Connected by', addr while 1: data = conn.recv(1024) if not data: break conn.send(data) conn.close() file: sockclient.py # Echo client program from socket import * HOST = 'daring.cwi.nl' # the remote host PORT = 50007 # the port used by server s = socket(AF_INET, SOCK_STREAM) s.connect(HOST, PORT) s.send('Hello, world') data = s.recv(1024) s.close() print 'Received', `data`

———

Text processing: regular expressions

file: cheader1.py #! /usr/local/bin/python import sys, regex from string import strip pattDefine = regex.compile( '^#[\t ]*define[\t ]+\([a-zA-Z0-9_]+\)[\t ]*') pattInclude = regex.compile( '^#[\t ]*include[\t ]+[<"]\([a-zA-Z0-9_/\.]+\)') def scan(file): count = 0 while 1: # scan line-by-line line = file.readline() if not line: break count = count + 1 n = pattDefine.match(line) # save match length if n >= 0: name = pattDefine.group(1) # matched substring body = line[n:] print count, name, '=', strip(body) elif pattInclude.match(line) >= 0: regs = pattInclude.regs # start,stop a, b = regs[1] # of group 1 filename = line[a:b] # slice out print count, 'include', filename if len(sys.argv) == 1: scan(sys.stdin) # no args: read stdin else: scan(open(sys.argv[1], 'r')) # arg: input file name % cheader1.py test.h 1 include stdio.h 2 include usr/local/include/Py/Python.h 4 SPAM = 5 SHOE_SIZE = 7.5 7 include local_constants.h 8 PARROT = dead + bird

———

Text processing: splitting files by columns

String.split returns a list of column strings

"eval" evaluates a Python expression string

file: summer.py import string, sys def summer(numCols, fileName): sums = [0] * numCols for line in open(fileName, 'r').readlines(): cols = string.split(line) for i in range(numCols): sums[i] = sums[i] + eval(cols[i]) return sums if __name__ == '__main__': print summer(eval(sys.argv[1]), sys.argv[2]) % summer.py cols file

———

System interfaces: regression tests

#!/usr/local/bin/python import os, sys # get unix, python services from stat import ST_SIZE # file stat record from glob import glob # file-name expansion from posixpath import exists # file exists test from time import time, ctime # time functions print 'RegTest start.' print 'user:', os.environ['USER'] # environment variables print 'path:', os.getcwd() # current directory print 'time:', ctime(time()), '\n' program = sys.argv[1] # two command-line args testdir = sys.argv[2] for test in glob(testdir + '/*.in'): # for all *.in files if not exists(test + '.out'): # no prior results command = '%s < %s > %s.out 2>&1' os.system(command % (program, test, test)) print 'GENERATED:', test else: # backup, run, compare os.rename(test + '.out', test + '.out.bkp') command = '%s < %s > %s.out 2>&1' os.system(command % (program, test, test)) command = 'diff %s.out %s.out.bkp > %s.diffs' os.system(command % ((test,)*3) ) if os.stat(test + '.diffs')[ST_SIZE] == 0: print 'PASSED:', test os.unlink(test + '.diffs') else: print 'FAILED:', test, '(see %s.diffs)' % test print 'RegTest done:', ctime(time()) % regtest.py shrubbery test1 RegTest start. user: mark path: /home/mark/stuff/python/testing time: Mon Feb 26 21:13:20 1996 FAILED: test1/t1.in (see test1/t1.in.diffs) PASSED: test1/t2.in RegTest done: Mon Feb 26 21:13:27 1996

———

Other things that weren't covered

Embedding and subclassing Tkinter GUIs

CGI scripts in Python, HTMLGen

Numeric Python examples

ILU (CORBA) examples

ActiveX/COM PythonWin examples

And more: see Programming Python, Appendix A

———
And finally...

"Nobody expects the Spanish Inquisition..." Questions?

———
Copyright 1997,

Mark Lutz