530 likes | 723 Views
Python Foundations. by Chris Gahan (( In Stereo where Available )). TRICK #1. Don’t Repeat Yourself If everything is defined once, then radically changing the behaviour of your program is trivial. TRICK #2. Get your program running on real data as soon as possible. TRICK #3. Test it!
E N D
Python Foundations by Chris Gahan (( In Stereo where Available ))
TRICK #1 • Don’t Repeat Yourself • If everything is defined once, then radically changing the behaviour of your program is trivial.
TRICK #2 • Get your program running on real data as soon as possible
TRICK #3 • Test it! • Even if you don’t have fancy test cases, make some little bit of code at the end of the program to test its functionality as you’re developing it. • I like to break my programs into a bunch of modules with tests in the ‘if __name__ == “__main__”:’ block • when you execute the file, the tests run • when you import it as a module, the tests are ignored
TRICK #4 • Use as much of Python’s libraries and built-in functionality as you can • Python’s built-in stuff is a solid foundation • There are solutions to many many problems in the standard library • Use lists and dicts for as much as you can • writing custom classes when you can use a list or dict will overcomplicate your code
TRICK #5 • The Zen of Python • Execute “import this” in the interpreter
Things you should know • Exceptions are awesome • But don’t over-use them • Decorators are cool • But you rarely need them • List comprehensions and Generators are wicked • Use them as much as possible! • Rethinking your problems as a series of generators or list transformations is an excellent habit to get into
More things you should know (about performance) • Appending strings is slow • Use lists and ‘’.join(list) them! • Searching lists is slow • Use sets or dicts! • Comparing lists is slow • Use sets! • List comprehensions are fast! • Use them as much as possible • If your program still isn’t fast enough, use Psyco or Pyrex! • Psyco optimizes code automatically (faster) • Pyrex generates C code which can be compiled (fastest)
Everything is an object • Lists are objects • Functions are objects • Classes are objects • Types are objects (IntType, ClassType, TypeType, etc.) • Dicts are objects • Objects are objects • Internally, all Objects are secretly Dicts!
Lists • This is your bread and butter in Python. Lists are everything: • list = [1,2,3,4,Ninja(),”rumplestiltskin”] • Handy methods: • list.append(5) • Stick 5 on the end of the list • list.extend([5,6,7]) • Append the contents of [5,6,7] to the list • list.pop(position) • Yank off an element from the list and hand it to you. If you don’t specify the position, it pops off the last element. • list.reverse() • Reverse the list • list.sort() • Sort the list • list.index(item) • Return the position of item in the list
Slicing • Lets you grab chunks from a list or a string. • list[5:9] • Grabs elements 5,6,7,8 • list[-3:-1] • Negative indexes mean “from the end”, -1 being first from the end, -2 being second from the end, etc.. So this would grab two elements: the 3rd and 2nd from the end. • list[:4] • Grabs elements 0,1,2,3 • list[6:] • Start at element 6 and grab all the rest of the elements until the end • list[:] • Grab all elements (make a copy of the entire thing) Note: The off-by-one thing (where it ignores the last element in the slice) is there for a good reason – it makes slice math super easy! (It’s the same reason that range(a,b) ignores the last element ‘b’)
Slicing Strings • Since strings are also technically lists of characters, they can also be sliced • To copy a string, take a slice that’s the entire string: • newString = oldString[:]
Trivia • Did you know that slices are actually OBJECTS? It’s TRUE! • You can make an object that returns its own custom slice objects which return anything you want • SQLObject does this when you slice a database query result – it uses “LIMIT” and “OFFSET” to get the chunk of the slice, resulting in mad speed!
Stupid Tuple Tricks • Tuples are like lists, but static • once you define a tuple, you can’t modify it • Whenever you use a comma in Python, a tuple is secretly created. For example: • a = 1, 2, 3 • open(“file.txt”, “r”) • person1, person2 = “Muhammed”, “Shareef” • a, b = b, a Internally, function parameters are tuples. Assigning two values at once A clever way to swap two variables
Kinds of Strings • Different kinds of strings: • Raw strings ignore escape codes (\n, \x, etc) • Great for regexes – you don’t have to go: \\t, \\w, \\s, etc..
String operations • s.replace(‘victim’, ‘replacement’) • Replace all occurrences of victim • s.strip([chars]) • Remove leading/trailing whitespace and newlines (or, remove leading/trailing [chars]) • s.split([delimiter]) • Break a string up into pieces and return them as a list of strings. The delimiter is whitespace by default. • You want more? Hit TAB in ipython!
Formatting Text for Output • Want to format text for output? • If you have a bunch of elements you want to print nicely, use “, “.join(list) • If you want to print strings, instead of: • “hi “ + name + “, how are you?” • …you can do: • “hi %s, how are you?” % name • Or • “hi %(name)s, how are you?” % locals()
String Interpolation • String interpolation lets you substitute placeholders (%s, %d, etc.) in a string (just like printf in C)
Why string interpolation? • Because when you have lots of variables in the output, it becomes annoying to keep track of where your quotes end. (Also, typing “++“ requires hitting shift a lot – it’s easy to mess it up). • “name: “+name+”, age: “+age+”, city: “+city+”, province: “+province+”, IP: “+ip+”, favorite colour: “+favorite_colour • …is harder to read than: • “name: %s, age: %s, city: %s, province: %s, IP: %s, favorite colour: %s” % (name, age, city, province, ip, favorite_colour) • …which is harder to read than: • “name: %(name)s, age: %(age)s, city: %(city)s, province: %(province)s, IP: %(ip)s, favorite colour: %(favorite_colour)s” % locals() • Of course, Ruby has the prettiest string interpolation: • “name: #{name}, age: #{age}, city: #{city}, etc..”
Files • Files are great in python • f = open(“filename.txt”)
Making lists pretty • Even though Python usually cares about indentation, lists don’t… so get creative! Note: You can have an extra comma on the last item to make cutting and pasting and shifting lines around easier!
Making dicts pretty Dicts let you use that extra comma too…
Making function calls pretty • Sometimes you need a huge number of function parameters. There’s a couple ways to make this readable: There’s that extra comma again!
Functions • Standard function • You can set the default value for a parameter (in this case, None). • These are called keyword arguments
“if” statements • You can do some neat tricks in “if” statements. • Compare identity with the “is” and “is not” operators: • if theSocket is not None: • if hand.contents() is None: • Checking if stuff is empty: • if []: => false • if “”: => false • if None: => false • if 0: => false
“if” statements • There’s also the handy “elif” construct: (That’s right, Python has no switch statement!)
Functions • Inline functions are kinda gross and very limited (they can only execute one statement, and it’s returned by default), but they’re sometimes handy. • It’s usually better to just “def” a function. (List comprehensions are better for this, by the way…)
Capturing Function Parameters • You can capture all the parameters passed to a function in a list by naming one parameter *args:
Capturing Function Parameters • You can also get a dictionary of all the keyword arguments
Using the “Apply” method • Apply lets you call a function and pass the parameters in as a list. For example, using the “cmp” (compare) function (which returns -1 for less than, 0 for equal, 1 for greater than):
But you don’t actually need apply… • You can actually do the same thing by putting the parameters in a list and “dereferencing” it with *list:
And it works for dicts too! • Dictionaries can be dereferenced by doing **dict:
Regexes • Regexes can be executed on a string directly: • match = re.match(‘expression’, ‘string’) • OR, they can be compiled first for extra speed: • compiled_regex = re.compile(‘expression’) • match = compiled_regex.match(‘string’) • When you do a .match() or a .search(): • No match returns None • A match returns a re match object, which contains: • groups() • group([group number]) • groupdict() (if you used named groups: “(?<name>expression)”)
Decorators • Decorators let you add wrapper code around methods and classes The New Way The Old Way
Static Methods / Class Methods • Oh yeah, I forgot to mention… • Static methods are methods that you can call on an instance or the class itself • They don’t take “self” as a parameter, so they can’t operate on the object. They’re just helper methods. • Class methods are called on classes only and receive the class as the first argument (instead of “self”) • Useful when you have a big class hierarchy and you want the parent class to do things to the child classes.
Docstrings, PyDoc, iPython • Docstrings rule. • It’s why everything in ipython has help for it • Whoever invented them was a genius, because they’re elegant and powerful: (It’s common to use triple-quotes because they let you write multi-line docstrings, and they kinda look nicer, but “regular strings” work too.)
List Comprehensions • List comprehensions make it simpler to do a really common task: computing something for every element in a list and putting the result in another list. • Check out that SAVINGS!
List Comprehensions • They can also work as filters. • Here’s how you filter a list of numbers and return only the even numbers:
Generators • Generators are special objects that spit out values one at a time as requested by the caller. • They can result in huge memory savings when processing large batches of data • They’re also great for implementing things like pipes, or procedurally generated sequences
Generators • To make your function a generator, just use “yield <value>” instead of “return <value>” • Calling a generator returns a generator object • Generator objects have a .next() method that returns the next value in the sequence • Generators maintain their state between calls to .next()
Generators • Example:
Generators • Another example:
Generator Expressions • Identical to list comprehensions, except that the result is a generator instead of a list. • for square in ( num**2 for num in numbers ): • print “you got yourself a square! => ”, square
Making programs flexible • It makes it much easier to write code when you can change it easily • I constantly modify my programs as I’m going, and as such, I’ve developed some good tricks to make that easier. • Writing your program as if it’s an API that you can call from the interpreter is an easy way of testing it • see altavista.py