# problem 1 x = 1 y = x x = 2 print x, y # problem 2 x = [1, 2] y = [x, 5] x.append(3) print y def square(x): return x*x print square(4) f = square print f(4) def fxy(f, x, y): return f(x) + f(y) print fxy(square, 3, 4) f = lambda x: x*x print f(3) print fxy(lambda x: x*x*x, 3, 4) x = ['python', 'perl', 'java', 'c', 'haskell', 'ruby'] print sorted(x) print sorted(x, key=len) def inc(x, amount=1): return x+amount print inc(5) print inc(5, 4) print inc(x=5, amount=4) def f(x): print "f is called with", x return x print "before defining inc" def inc(x, amount=f(1)): return x + amount print "after defining inc" print inc(5) for a in [1, 2, 3, 4]: print a for a in (1, 2, 3, 4): print a for k in {"a": 1, "b": 2}: print k for c in "hello": print c ",".join(["a", "b", "c"]) ",".join({"a": 1, "b": 2}) ",".join("hello") max([1, 2, 3, 4]) max("hello") max({"a": 1, "b": 2}) x = iter([1, 2, 3, 4]) x.next() x.next() x.next() x.next() x.next() x = iter("abc") x.next() x.next() x.next() x.next() class yrange: def __init__(self, n): self.i = 0 self.n = n def __iter__(self): return self def next(self): i = self.i if i < self.n: self.i = i + 1 return i else: raise StopIteration() y = yrange(5) for a in y: print a # [1, 2, 3, 4] is an iterable object. # x = iter([1, 2, 3, 4]) gives an iterator. # next() method can be called on an iterator. y = yrange(5) print list(y) print list(y) class zrange: def __init__(self, n): self.n = n def __iter__(self): return yrange(self.n) z = zrange(5) print list(z) print list(z) def yrange(n): i = 0 while i < n: yield i i += 1 y = yrange(3) print y.next() y.next() y.next() y.next() def f(): print "begin f" yield 1 print "after yielding 1" yield 2 print "end" a = f() print a a.next() a.next() a.next() max(yrange(4)) sum(yrange(4)) def squares(numbers): for n in numbers: yield n*n print sum(squares(xrange(1000000))) %%file a.txt 1 2 3 4 5 def toint(strings): for s in strings: yield int(s) print sum(toint(open("a.txt"))) print sum(squares(toint(open("a.txt")))) # the regular way is result = 0 for line in open("a.txt"): n = int(line) result += n print result # Solution to joiniters def joiniters(x, y): for a in x: yield a for b in y: yield b # solution to iterappend def iterappend(x, end): return joiniters(x, [end]) print sum(iterappend([1, 2], 3)) x = range(10) [a*a for a in x] [a*a for a in x if a % 2 == 0] %%file square.py def square(x): return x*x def cube(x): return x*x*x # Find all line containing function definations [line for line in open("square.py") if line.startswith("def")] # fine all function names [line.split("(")[0][len("def "):] for line in open("square.py") if line.startswith("def")] %%file a.csv a,b,c 1,2,3 1,4,9 1,8,27 [line.strip("\n").split(",") for line in open("a.csv")] def squares(values): return [x*x for x in values] print sum(squares(xrange(1000000))) squares_list = [x*x for x in xrange(1000000)] squares_gen = (x*x for x in xrange(1000000)) squares_gen sum(squares_gen) sum((x*x for x in xrange(1000000))) sum(x*x for x in xrange(1000000)) def grep(pattern, fileobj): return (line for line in fileobj if pattern in line) def printlines(lines): for line in lines: print line.strip("\n") fileobj = open("square.py") lines = grep("def", fileobj) printlines(lines) %%file hello.py def hello(name): print "hello", name def joiniters(x, y): for a in x: yield a for b in y: yield b fileobj1 = open("square.py") fileobj2 = open("hello.py") lines = joiniters(fileobj1, fileobj2) lines = grep("def", lines) printlines(lines) def readfiles(filenames): """Reads all files and returns iterator over lines.""" for filename in filenames: for line in open(filename): yield line lines = readfiles(["square.py", "hello.py"]) lines = grep("def", lines) printlines(lines) !gzip hello.py !ls *.gz import gzip def xopen(filename): if filename.endswith(".gz"): return gzip.open(filename) else: return open(filename) def readfiles(filenames): """Reads all files and returns iterator over lines.""" for filename in filenames: for line in xopen(filename): yield line lines = readfiles(["square.py", "hello.py.gz"]) lines = grep("def", lines) printlines(lines) # countiter solution def countiter(it): count = 0 for x in it: count += 1 return count def countiter(it): return sum(1 for x in it) import itertools print list(itertools.chain([1, 2, 3, 4], [5, 6])) for a, b in itertools.izip("hello", "world"): print a, b x = itertools.izip("hello", "world") print x.next() # solution to izip def izip(x, y): x = iter(x) y = iter(y) while True: yield x.next(), y.next() for a, b in izip([1, 2, 3], "hello"): print a, b for i, c in enumerate("hello"): print i, c def myenumerate(it): return izip(numbers(), it) def numbers(): i = 0 while True: yield i i += 1 for i, c in myenumerate("hello"): print i, c def exp(x, n): print "exp", x, n if n == 0: return 1 else: return x * exp(x, n-1) print exp(2, 10) def fast_exp(x, n): print "fast_exp", x, n if n == 0: return 1 elif n % 2 == 0: return fast_exp(x*x, n/2) else: return x * fast_exp(x, n-1) print fast_exp(2, 100) def flatten_list(x, result=None): """Flattens a nested list. >>> flatten_list([[1, 2], [3, 4, [5]]]) [1, 2, 3, 4, 5] """ if result is None: result = [] for a in x: if isinstance(a, list): flatten_list(a, result) else: result.append(a) return result print flatten_list([1, 2, 3]) print flatten_list([[1, 2], [3, 4, [5]]]) def flatten_dict(d, result=None, prefix=None): if result is None: result = {} for k, v in d.items(): if prefix is None: key = k else: key = prefix + "." + k if isinstance(v, dict): flatten_dict(v, result, prefix=key) else: result[key] = v return result flatten_dict({'a': 1, 'b': {'x': 2, 'y': 3, 'z': {'p': 5}}, 'c': 4}) def json_encode(data): if isinstance(data, bool): if data: return "true" else: return "false" elif isinstance(data, (int, float)): return str(data) elif isinstance(data, str): return '"' + data + '"' elif isinstance(data, list): elements = [json_encode(d) for d in data] values = ", ".join(elements) return "[" + values + "]" print json_encode(True) print json_encode(1.234) print json_encode([1, 2, 3, True, "hello", [3, 4]]) print json_encode({"a": [1, True], "b": {"name": "hello"}}) # {"a": [1, true], "b": {"name": "hello"}} indent = 0 def trace(f): def g(n): global indent print "| " * indent + "|-- " + f.__name__, n indent += 1 value = f(n) indent -= 1 return value return g def memoize(f): cache = {} def g(n): if n not in cache: cache[n] = f(n) return cache[n] return g import time #fib = trace(fib) #fib = memoize(fib) @memoize @trace def fib(n): if n == 0 or n == 1: return 1 else: return fib(n-1) + fib(n-2) t0 = time.time() print fib(5) t1 = time.time() print "took %f seconds" % (t1-t0) def profile(f): def g(): ... return g def timepass(): for i in range(100000): for j in range(100): x = i*j timepass = profile(timepass) timepass()