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 lutz@learning-python.com.
Contents
- Talk outline
- But first: the book plug...
- I. General Overview
- II. Python Resources
- 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
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:
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...
- 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
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()
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)
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
python-help@python.org - 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]
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 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
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!
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
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
