The Python Programming Language
Presented on 8 June 2004 at the Western Cape Linux Users' Group meeting at University of Cape Town, South Africa.
Formats
Available in the following formats:
Notes
Why Python?
===========
How do you evaluate a programming language?
-------------------------------------------
Simplistic: CPU time, Memory usage, Lines of Code
CPU is reasonably cheap, and memory is next, and developer time is the most
expensive.
At a higher level, the developer time issue comes down to ease of use, low
overhead, solid standard and third party libraries, and similar issues.
Python offers some advantages in these areas.
What's so great about Python?
-----------------------------
Python Language:
- - - - - - - - -
Simple,Elegant,Reliable,Powerful
Simple:
- Easy to read and understand
- Easy to use
- Easy to achieve most things
- Fits in your brain
- No unintended side-effects
Elegant:
- Compact, readable code
- Low syntax overhead
- Expressive
- No visual/semantic conflicts
Reliable:
- Robust
- Tested
- Obvious
- Less places for errors to hide
- Open Source
- Errors per KLOC ratio reasonably constant between programming langauges
Powerful:
- Able to achieve almost anything
- Little code goes a long way
- Can harness existing code in other languages or platforms
- Extensibility, Jython, IronPython
- Flexible
- Portable, cross-platform
Standard Library:
- - - - - - - - - -
Batteries included!
- Protocols: HTTP, FTP, SMTP, POP3, IMAP, NNTP, ...
- Markup support: HTML, SGML, XML
- File formats: Mailbox, CSV, ZIP, TAR
- Servers: HTTP, XMLRPC
- Debugging, logging, URL manipulation, profiling, regular expressions, ...
Third Party:
- - - - - - - - -
Twisted
- Protocols: DNS, FTP, IRC, Jabber, MSN, AOL/Oscar, Shoutcast, SIP, ...
Cheetah
- Powerful template language (like Mason, Velocity, Smarty)
Webware
- Servlet-based application server
Zope
- Python Application Server, used for CMS, Plone, &c.;
Quotes
------
Bruce Eckel: Designed to maximise productivity, doesn't treat me like I'm
stupid, my first guess is usually right, focus on concepts
Who Uses Python
---------------
Industrial Light & Magic relies on Python in their production pipeline,
every computer-generated image from ILM has had Python involved in its
creation somehow.
Google!
Various computer games, from the massively-multiplayer EVE mostly
developed in Python to games such as Temple of Elemental Evil and Ages
of Myst which embeds it as their game scripting language.
Mark Shuttleworth's Thawte Consulting used Python as a productive way to
manage large codebases in a rapidly evolving way.
In the open source world: RedHat's install system (anaconda) is written
in Python, as is Gentoo's package management system, portage.
NASA's Integrated Planning System uses Python as the standard agile
language, and NASA's Mission Control Centre uses Python.
Data Types
==========
Strings
-------
"asdf"
'asdf'
"""John said "Foo is a bad dog", and walked away."""
'''Foo is Peter's dog'''
-----
print "Hello"
print "Hello",
print "There"
variables and assignment
------------------------
a = 1
b = a + 5
c = (b * 3) + 2
a, b = 6 + 4, 1 + 3
a, b = b, a
raw_input (using a function)
---------
name = raw_input("Give me your name")
Lists/sequences
---------------
l = []
l2 = ["a", 2, b * 3]
print l2[0]
l.append(3)
l2.remove(2)
Dictionaries ("Associative arrays")
------------
d = {}
d['hello'] = "there"
d['Peter'] = "Pan"
del d['hello']
d.get('foo', None)
d.has_key('Peter')
d.setdefault('Mozilla', 0)
d.keys()
d.values()
d.items()
Formatting strings
------------------
"I have %d apples in my %s" % (1, "bag")
Sequence operations
-------------------
Strings are also sequences
"Slices" are parts of sequences
"Harry Potter"[1:4] is "arr"
"Harry Potter"[7:-2] is "ott"
Blocks
======
indentation
-----------
Indentation is used as the only means to determine which block a piece
of code belongs to:
C:
if (a)
if (b)
a = 0
if (c)
b = 1
if (d)
e = 1
But that maps to, in reality:
if (a) {
if (b) {
a = 0
}
if (c) {
b = 1
}
}
if (d) {
e = 1
}
This is a visual/semantic conflict.
Programmers should be indenting anyway. It's even less work to just not
type the braces. Also forces code to look somewhat uniform, and easy to
read.
pass
----
"Do nothing, but fill a line." Necessary for an empty block.
for
---
for fruit in ["apple", "banana"]:
print "%s is a fruit, I like them." % (fruit)
for line in file("/etc/fstab"):
print line
for letter in "Hello there":
print letter
while
-----
x = 1
while x < 10:
print x
x += 1
if
--
x = 1
y = 5
if x > y:
print "%s is greater than %s" % (x, y)
else x < y:
print "%s is smaller than %s" % (x, y)
else:
print "%s has the same value as %s" % (x, y)
functions
---------
def twice(a):
b = a * 2
return b
Classes
=======
class classname (parentclass1, ...):
classvar = 1
def method1(self, arg1, ...):
return "stuff"
Classes are ways to create new types of objects. Everything in Python
is an object.
Classes explain how to interact with the object, and should contain data
about the specific instance of an object. Objects are data and
behaviour.
Classes also explain to the rest of the language how the objects of
their type interact with other objects. This allows you to add an
integer to a time object, for example. It also allows you to change how
the object displays itself as a string. Or how sequence operators work
on the object.
Explaining Object Orientation is beyond the scope of this talk.
List comprehensions
-------------------
Powerful and elegant way of creating one list from another, based on the
values of the first list.
Say you want to double everything in a list:
l2 = [x * 2 for x in l1]
Which means, for every item in list l1, put double that item in list l2.
Let's say you want to remove certain items in a list to create another
list, based on some comparison or function:
l2 = [x for x in l1 if x > 5]
Which means, for every item in list l1, put that item in list l2, but
only if it is greater than 5.
You can combine this easily enough:
l2 = [3 * x for x in l1 if x < 27]
You don't have to provide only one return value:
l2 = [(x, x ** 2) for x in [0, 1, 2, 3, 4, 5, 6, 7, 8] if x % 2 == 0]
This will create a list, each item is the original number and that
number squared, starting from 0 and ending at 8, but only the even
numbers.
This isn't just useful for showing off.
Let's say you have a map of people you know and their phone numbers.
p = {
'John': '021 797 5432',
'Peter': '011 872 7652',
'Joan': '031 381 8127',
'Mary': '083 143 1823',
'Barry': '021 432 1943',
}
Now you want to know who you know in Cape Town:
l2 = ["%s lives in Cape Town, and the number is %s" %
(person, number) for person, number in p.items() if number.startswith('021')]
for a in l2:
print a
Barry lives in Cape Town, and the number is 021 432 1943
John lives in Cape Town, and the number is 021 797 5432
Batteries Included!
===================
-----
import smtplib
from email.MIMEText import MIMEText
fp = open('/tmp/message')
# Create a text/plain message
msg = MIMEText(fp.read())
me = 'me@my.domain'
you = 'you@your.domain'
msg['Subject'] = 'That stuff you wanted'
msg['From'] = me
msg['To'] = you
s = smtplib.SMTP()
s.connect()
s.sendmail(me, [you], msg.as_string())
s.close()
mailbox
-------
import email
import mailbox
maildir = mailbox.Maildir('Maildir', email.message_from_file)
for mail in maildir:
print mail["Date"]
Making a mailing list program from just these few modules would be
simple and functional. The email module provides the ability to
manipulate the message, the mailbox module provides the ability to
receive the message, and the smtplib module provides the ability to send
the message.
simple mailing list program
---------------------------
import smtplib
import email
import mailbox
maildir = mailbox.Maildir('Maildir', email.message_from_file)
to = ['first1@company1', 'first2@company2', ... ]
listprefix = '[ListName] '
s = smtplib.SMTP()
s.connect()
for mail in maildir:
mail['List-Id'] = foo
if listprefix not in mail['Subject']:
mail['Subject'] = listprefix + mail['Subject']
mail['From'] = 'Original sender hidden
'
s.sendmail(me, [you], mail.as_string())
s.close()
SQLObject
---------
from SQLObject import *
__connection__ = MySQLConnection(db='foo', user='root')
class Subscriber(SQLObject):
address = StringCol(alternateID=True)
name = StringCol()
added = DateTimeCol()
admin = BoolCol(default=False)
bounces = IntCol(default=0)
Subscriber.createTable()