Upload
others
View
7
Download
0
Embed Size (px)
Citation preview
A Whirldwind Tour of Python
A taste for nonPythonistas,tidbits for novice Python programmers
and cute pictures for the nonprogrammers
Copyright 2004 Tommi Virtanen <[email protected]>This work is licensed under the Creative Commons Attribution License.To view a copy of this license, visit http://creativecommons.org/licenses/by/1.0/or send a letter to Creative Commons, 559 Nathan Abbott Way,Stanford, California 94305, USA.
Highlevel, indentationbased syntax
import sets
seen = sets.Set()
for line in file(filename):
line = line.rstrip()
lower = line.lower()
if lower not in seen:print line
seen.add(lower)
Interactive• REPL (readevalprint loop)
Allows quick experiments
>>> 'The happy cat ran home.'.upper()'THE HAPPY CAT RAN HOME.'>>> 'The happy cat ran home.'.find('cat')10>>> 'The happy cat ran home.'.find('kitten')-1>>> 'The happy cat ran home.'.replace('cat', 'dog')'The happy dog ran home.'
Online help>>> help('text'.find) Help on builtin function find:
find(...) S.find(sub [,start [,end]]) > int Return the lowest index in S where substring sub is found, such that sub is contained within s[start,end]. Optional arguments start and end are interpreted as in slice notation. Return 1 on failure.
>>>
Carrot vs. the whip (vs. anarchy)
● Very flexible language● Extremely few builtin rules● Strong conventions, good taste● “There's Only One Way To Do It”
Naming conventions
● FOO: constant● Foo: class● foo: your average variable● _foo: internal implementation detail● __foo: internal, namespace rules “protect” it● __foo__: __init__, __str__, __eq__, ...
Stringification and representation
● str(), __str__: userfriendly output● repr(), __repr__: programmerfriendly output● print stringifies implicitly● REPL repr's return values
>>> s='a'>>> s'a'>>> print sa>>> print repr(s)'a'>>>
Data types
● Strings● Numbers: integers, floats● Sequences: lists, tuples● Dictionaries, Sets● Functions, classes, etc.
Strings
● Methods of string object– s.lower(), s.split(',')
● Oldstyle: module string– string.lower(s), string.split(s, ',')
● Strings are also sequences– len(s), s[3:6]
● Unicode and raw strings– u'ääliö', r'\n'
'string\n'”isn't this fun”
'''multiline'''
”””Docstrings looklike this quiteoften.”””
Numbers
● int(), float()● hex(), oct()● 42L● Bored now.
Sequences
● Tuples are (), lists are []● Tuples also happen implicitly: 1, 2
– Beware the hidden comma
● Tuples are immutable● “Think math”: tuples are ordered
groups of fixed number of things, lists are variablelength and contain mostly heterogenous items
return (“foo”, +”bar”)
return (“foo” +”bar”)
return (“foo”, ”bar”)
Dictionaries and Sets
● Dictionaries map keys to values– Keys must be immutable so their hash value doesn't
change
● Sets are like dicts, but without the values● Keys are not in any sane order
– Not repeatable
Code organization
● Functions– def plus(a, b):
return a+b
● Classes– class PlusX:
def __init__(self, x):self.x = x
def plus(value):return self.x + value
Code organization
● Modules, packages– import something
– import something.somewhere
– from something.somewhere import Stuff, Thing
/path/to
Must be inPYTHONPATH(aka sys.path)
package module/ / / .py
Must contain__init__.py
package
The % operator
● Much like sprintf● %s is str, %r is repr● Can use sequences (lists) and mappings (dicts)
'%(name)s is %(value)d' % { 'name': 'The answer', 'value': 42,}
'%s: %r' % (something, other)
Exceptions$ cat exceptions.py def plus(a, b): return a+b
def plusTwo(x): return plus(x, 2)
plusTwo('foo')$ python exceptions.py Traceback (most recent call last): File "exceptions.py", line 7, in ? plusTwo('foo') File "exceptions.py", line 5, in plusTwo return plus(x, 2) File "exceptions.py", line 2, in plus return a+bTypeError: cannot concatenate 'str' and 'int' objects$
Your own exceptionsclass FibonacciNegativeIndexError(Exception): """Index must be positive"""
def __str__(self): return '%s: %r' % (self.__doc__, self.args[0])
def fibo(n): if n < 0: raise FibonacciNegativeIndexError, n elif n < 2: return n else: return fibo(n2) + fibo(n1)
if __name__ == '__main__': import sys for arg in sys.argv[1:]: n = int(arg) print fibo(n)
Handling exceptionsif __name__ == '__main__': import sys m = MemoizedFibo() for arg in sys.argv[1:]: n = int(arg) print m.get(n)
class MemoizedFibo: def __init__(self): self.memo = {}
def get(self, n): try: return self.memo[n] except KeyError: if n < 0: raise FibonacciNegativeIndexError, n elif n < 2: return n else: r = self.get(n2) + self.get(n1) self.memo[n] = r return r
Generalize memoizedef fibo(n): ...
def memoize(fn): memo = {} def _get(*args, **kwargs): hashable = (tuple(args), tuple(kwargs.items())) try: return memo[hashable] except KeyError: r = fn(*args, **kwargs) memo[hashable] = r return r return _get
if __name__ == '__main__': import sys f = memoize(fibo) for arg in sys.argv[1:]: n = int(arg) print f(n)
But that was slow!def fibo(n, me): if n < 0: raise FibonacciNegativeIndexError, n elif n < 2: return n else: return me(n2, me) + me(n1, me)
if __name__ == '__main__': import sys f = memoize(fibo) for arg in sys.argv[1:]: n = int(arg) print f(n, f)
But that was ugly!class FibonacciNegativeIndexError(Exception):
...def fibo(n):
...def memoize(fn):
...fibo = memoize(fibo)
if __name__ == '__main__': import sys for arg in sys.argv[1:]: n = int(arg) print fibo(n)
Generating the whole sequence
def fibo(): thisnum, nextnum = 0, 1 while True: yield thisnum thisnum, nextnum = nextnum, thisnum + nextnum
if __name__ == '__main__': for n in fibo(): print n
Unit Tests
def extractSizeFromName(filename): base = filename.split(':', 1)[0] for part in base.split(','): if part.startswith('S='): size = part[len('S='):] try: size = int(size) except ValueError: size = None return size
class MaildirFilenameSizeTestCase(unittest.TestCase): def check(self, text, size): """Check that the given filename parses with expected results. Also try with :info appended, and try with confusing S= in the info.""" self.assertEquals( maildirquota.extractSizeFromName(text), size) self.assertEquals( maildirquota.extractSizeFromName(text+':someInfo'), size) self.assertEquals( maildirquota.extractSizeFromName(text+':someInfo,S=3141592'), size)
def testSimple(self): self.check('1056827511.M7908229P20206Q1.foo,S=159', 159)
def testNoSize(self): self.check('1056827511.M7908229P20206Q1.foo', None)
def testBrokenSEqualsOnly(self): self.check('1056827511.M7908229P20206Q1.foo,S=', None)
def testBrokenSEqualsChar(self): self.check('1056827511.M7908229P20206Q1.foo,S=bar', None)
def testBrokenSEqualsNumberAndChar(self): self.check('1056827511.M7908229P20206Q1.foo,S=42bar', None)
def testSupportsLotsOfCommas(self): self.check('1056827511.M7908229P20206Q1.foo,S=42,X=bar', 42)
Systems programming#!/usr/bin/python"""Output a SHA1 hash and size of data read."""
import sys, sha
for filename in sys.argv[1:]: file = open(filename) filelen = 0 hash = sha.new() while 1: bytes = file.read(4096) if not bytes: break hash.update(bytes) filelen += len(bytes)
file.close() print "%s %9d %s"%(hash.hexdigest(), filelen, filename)
Systems programming
#!/usr/bin/pythonimport sys, errno
for arg in sys.argv[1:]: try: arg = int(arg) except ValueError: print getattr(errno, arg.upper(), None) else: print errno.errorcode.get(arg, None)
#!/usr/bin/pythonimport sys, errno, os
for arg in sys.argv[1:]: try: arg = int(arg) except ValueError: arg = getattr(errno, arg.upper(), None)
if arg is not None: arg = os.strerror(arg) print arg
Nice interface to C#include <Python.h>#include <unistd.h>
/* int fchdir(int fd); */static PyObject *my_fchdir(PyObject *self,
PyObject *args) { int fd; int ret; if (!PyArg_ParseTuple(args, "i", &fd)) return NULL; ret = fchdir(fd); if (ret<0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } Py_INCREF(Py_None); return Py_None;}
static PyMethodDef my_methods[] = { { "fchdir", my_fchdir, METH_VARARGS, "fchdir(fd)" },
{NULL, NULL, 0, NULL}};
void initfchdir(void) { Py_InitModule("fchdir", my_methods);}
Pyrex: Even nicer
cdef extern from "unistd.h": int _fchdir "fchdir" (int) except 1
def fchdir(fd): return _fchdir(fd)
Now it's your turn!
● In REPL, count how many times the word “wood” appers in the string “If a woodchuck could chuck wood, how much wood would a woodchuck chuck?”
● Write a program called “turkuenergia” that outputs Fibonacci numbers 155 vertically, right justified.
● Write a program that reads standard input, counts different characters (az etc.), and outputs a report.
For more information
● Python 101: http://www.rexx.com/~dkuhlman/python_101/python_101.html
● Python 201: http://www.rexx.com/~dkuhlman/python_201/python_201.html
● Dive Into Python: http://diveintopython.org/toc/index.html
● Python Cookbook: http://aspn.activestate.com/ASPN/Cookbook/Python/
● More links: http://www.python.org/doc/Intros.html
Questions?
● Don't forget the Python Q&A planned for Sunday!
Thank You