[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
, while it
.]
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
.
PSA-sponsored Python Conferences
III. A first look at the language
A pragmatic interlude: system interfaces
Functions are objects: indirect calls
Classes are objects: factories
Methods are objects: bound or unbound
Modules are objects: metaprograms
Summary: Python tool-set layers
Text processing: regular expressions
Text processing: splitting files by columns
System interfaces: regression tests
Other things that weren't covered
Also see the
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
for more Python/C integration examples.
———
"And now, for something completely different..." Mark Lutz March 1997
———
A high-level overview of Python
Pointers to Python resources
A first look at the language
Real Python programs (as time allows)
———
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
———
———
Definitions
Features
Common Roles
History
Plus lots of hand-waving
———
———
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
Support for object-oriented development
Powerful programming constructs
Extendible and embeddable architecture
Remarkably clear syntax and coherent design
"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." :-)
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 ;-)"
———
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
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,...
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
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
———
UNIX (and Linux)
Windows 3.1, 95, NT
MS-DOS
Macintosh
OS/2
VMS
Next
Be OS
Amiga, Atari ST
And others
Compiled to portable byte-code (on import)
Tkinter GUI API: runs on X11, MS-Windows, Macs
PythonWin: ActiveX, MFC, COM, IDE, DLLs
MacPython: PPC, 68K, AppleEvents
The PythonWin IDE
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)
———
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)
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
———
———
The Internet
Books
Articles
Conferences
Training
———
———
Python's website
My website
starship.python.net/~lutz.home
O'Reilly's website
Python's FTP site
Python's general USENET newsgroup (and mail-list)
Python's technical help/support mail-list
CompuServe Python forum
go python
German-language email list
"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
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
: October '97, San Jose
Digital Creations seminars and training
See
———
———
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
———
———
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.
———
Numbers: 3.1415 Strings: 'spam' Lists: [1, [2, 'three']] Dictionaries: {'food':'spam', 'taste':'yum'} Tuples: (1,'spam', 4, 'U') Files: open('temp', 'r').read()
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
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!
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!
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'
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
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
In Python, everything is an object type.
Functions
Modules
Methods
Classes
Byte-compiled code
Stack tracebacks
Heterogeneous
Nestable
Shared object references
Dynamically resizable (most)
Operation categories: sequence, mapping, number
Nesting example
L = ['abc', [(1,2), ([3], 4)], 5]
———
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
———
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
———
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!
———
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
———
"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]
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!')
"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
"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!
———
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!
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
———
[See the
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
———
———
Shell tools
Data-structure classes
Graphical user interfaces
Persistent objects
Text processing
Plus lots of big, confusing examples
———
———
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
———
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
———
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
———
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']
———
#!/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
———
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,