Basic Python: Part 2
More Functions
Data Structures
Introduction to Modules
We’ve already know the basics of functions so let’s dive a little deeper.
• Default argument values
• We can provide a default value for any number of arguments in a function.
• Allows functions to be called with a variable number of arguments.
def connect(uname, pword, server = 'localhost', port = 9160):
# connecting code
• This function can be called a number of ways. connect('admin', 'ilovecats') connect('admin', 'ilovecats', 'shell.cs.fsu.edu') connect('admin', 'ilovecats', 'shell.cs.fsu.edu', 6379)
When functions arguments are not specified, they are called positional arguments.
Keyword arguments are of the form kwarg = value
. connect('admin', pword = 'ilovecats', server = 'shell.cs.fsu.edu', port = 6379)
If keyword arguments are used they must follow any positional arguments, although the relative order of keyword arguments is unimportant.
Parameters of the form
*param contain a variable number of arguments within a tuple. Parameters of the form
**param contain a variable number of keyword arguments.
def connect(uname, *args, **kwargs): print uname for arg in args: print arg for key in kwargs.keys(): print key, ": ", kwargs[key] connect('admin', 'ilovecats', server='localhost', port=9160)
def connect(uname, *args, **kwargs): print uname for arg in args: print arg for key in kwargs.keys(): print key, ": ", kwargs[key] connect('admin', 'ilovecats', server='localhost', port=9160)
Advanced List Usage
Tuples
Sets
Dictionaries
Looping
We’ve already reviewed basic list usage and seen some of the built-in functionality.
• Stacks
• Last in, first out.
>>> mystack = [1, 2, 3, 4, 5]
>>> mystack.append(6)
>>> mystack
[1, 2, 3, 4, 5, 6]
>>> mystack.pop()
6
>>> mystack
[1, 2, 3, 4, 5]
• Queues
• First in, first out.
• Use collections.deque for fast pops from the beginning.
>>> from collections import deque
>>> myqueue = [1, 2, 3, 4, 5]
>>> myfastqueue = deque(myqueue)
>>> myfastqueue deque([1, 2, 3, 4, 5])
>>> myfastqueue.append(6)
>>> myfastqueue deque([1, 2, 3, 4, 5, 6])
>>> myfastqueue.popleft()
1
>>> myfastqueue deque([2, 3, 4, 5, 6])
Lists can be used with a few useful functions to implement functional programming.
• filter()
• filter(function, sequence) filters items from sequence for which function(item) is true.
• Returns a string or tuple if sequence is one of those types, otherwise result is a list. def even(x): if x % 2 == 0: return True else: return False print(filter(even, range(0,30)))
Output: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28]
• map()
• map(function, sequence) applies function to each item in sequence and returns the results as a list.
• Multiple arguments can be provided if the function supports it. def square(x): return x**2 print(map(square, range(0,11))) def square(x, y): return x*y print(map(square, range(0, 11), range(0,11)))
Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
• reduce()
• reduce(function, sequence) returns a single value computed as the result of performing function on the first two items, then on the result with the next item, etc.
• There’s an optional third argument which is the starting value. def factorial(x, y): return x*y print(reduce(factorial, range(1,5)))
Output: 24
One can also define lambda functions within Python.
• Use the keyword lambda instead of def.
• Can be used wherever function objects are used.
• Restricted to one expression.
>>> print(map(lambda x: x**2, range(0,11)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
List comprehensions provide a nice way to construct lists where the items are the result of some operation.
The simplest form of a list comprehension is: [ expr for x in sequence ].
Any number of additional for and/or if statements can follow the initial for statement.
A simple example of creating a list of squares.
>>> squares = [x**2 for x in range(0,11)]
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100 ]
Here’s a more complicated example which creates a list of tuples.
>>> squares = [(x, x**2, x**3) for x in range(0,11) if x % 2 == 0]
>>> squares
[(0, 0, 0), (2, 4, 8), (4, 16, 64), (6, 36, 216), (8, 64, 512), (10, 100, 1000)]
The initial expression in the list comprehension can be anything, even another list comprehension.
>>> [[x*y for x in range(1,5)] for y in range(1,5)]
[[1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12], [4, 8, 12, 16]]
•
Tuples are very similar to lists except for two main points:
• Enclosed by parentheses.
• Immutable (but can contain mutable objects).
• Packing a tuple:
Unpacking a tuple:
>>> mytuple = 1, "two", [3, "four"]
>>> mytuple
(1, 'two', [3, 'four'])
>>> mytinytuple = "atom",
>>> mytinytuple
('atom',)
>>> a, b, c = mytuple
>>> print a, b, c
1 two [3, 'four']
Sets are an unordered collection of unique elements. We’ve already seen some set basics, but it is important to note that sets also support set comprehensions.
>>> a = {x for x in 'alphabet'}
>>> a set(['a', 'b', 'e', 'h', 'l', 'p', 't'])
Dictionaries support dict comprehensions as well.
>>> squares_dict = {x: x**2 for x in range(1,11)}
>>> squares_dict
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100}
A module is a file containing Python code. Our Fibonacci code file from the previous lecture could be a module.
Modules are referenced by their filename (minus the .py suffix). For example, fib.py can be referenced as “fib”. This is also available through the __name__ variable.
Modules are included using the import keyword. Functions defined in a module are available as a method of the imported module.
>>> import fib
>>> fib.even_fib(4000000)
4613732
It is important to note that executable statements in a module will execute when it is first imported.
Let’s say I create a module (greeting.py) which contains the following code: greeting.py
def greet(): print("Hello from a function!") print "Hello!"
>>> import greeting
Hello!
>>> greeting.greet()
Hello from a function!
By convention, all import statements should appear at the top of the .py file.
It is possible to import specific objects from a module. For example,
>>> from greeting import greet
Hello!
>>> greet()
Hello from a function!
Use from module import * to import all objects from a module.
When a module is imported, the interpreter will first search for a built-in module with the same name. If that fails, then it will search for the module in the list of directories given by the sys.path
variable.
>>> import sys
>>> sys.path
['', '/usr/local/lib/python2.7/dist-packages/D_Wave_One_Python_Client-1.4.1-py2.6-linuxx86_64.egg', '/usr/local/lib/python2.7/dist-packages/PyOpenGL-3.0.2a5-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/pip-1.1-py2.7.egg', '/usr/local/lib/python2.7/distpackages/Sphinx-....
Let’s use what we’ve learned today to solve another problem in Python.
A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2,
3 and 4. If all of the permutations are listed numerically or alphabetically, we call it lexicographic order. The lexicographic permutations of 0, 1 and 2 are:
012 021 102 120 201 210
What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?
driver.py
permute.py
from __future__ import print_function from permute import gen_permutation from itertools import permutations if __name__ == "__main__": num_digits = raw_input("Number of digits: ") digit_index = raw_input("Index of the permutation: ") result = gen_permutation(int(num_digits), int(digit_index)) print(result) def factorial(num):
# Returns the factorial of num return reduce(lambda x,y: x*y, [x for x in range(1,num+1)]) def gen_permutation(n, i):
# Find the first digit of the desired permutation f = factorial(n-1) first_digit = i/f
$ python driver.py
Number of digits: 10
Index of the permutation: 1000000
2783915460
# Calculate the permutations of the remaining digits rest_digits = [str(x) for x in range(0,n) if x != first_digit] perm_list = [''.join(x) for x in (permutations(rest_digits))]
# Construct the desired permutation i = i - first_digit*f return(int(str(first_digit) + perm_list[ i-1 ]))
I/O
Files
Errors and Exceptions