Use sequentially ordered statements to change program state, as in iPython
Pro:
Con:
In [ ]:
n = 100
primes = []
for p in range(3,n):
In [ ]:
In [ ]:
n = 100
primes = []
for p in range(3,n):
for x in range(2,p):
if p%x==0:
break
else:
primes.append(p)
print primes
In [ ]:
n
In [ ]:
In [ ]:
import prime_module
In [ ]:
print prime_module.primes
print prime_module.__file__
package = folder containing (possibly empty) __init__.py
Current working directory (cwd):
prime_module.py
[function: "def prime_list(n)..."]my_package
__init__.py
[empty]prime_module.py
[function: "def prime_list(n)..."]my_folder
prime_module.py
[function: "def prime_list(n)..."]
In [ ]:
from my_package import prime_module
print prime_module.primes
print prime_module.__file__
In [ ]:
from my_folder import prime_module
Write you code as functions. Pure functional programming: No statements only functions without side effects
Pro:
Con:
In [ ]:
n = 100
primes = []
for p in range(3,n):
for x in range(2,p):
if p%x==0:
break
else:
primes.append(p)
print primes
In [ ]:
def prime_list(n):
primes = []
for p in range(3,n):
for x in range(2,p):
if p%x==0:
break
else:
primes.append(p)
return primes
print prime_list(100)
In [ ]:
def prime_list(n):
primes = []
for p in range(3,n):
if is_prime(p):
primes.append(p)
return primes
def is_prime(p):
for x in range(2,p):
if p%x==0:
return False
else:
return True
print prime_list(100)
In [ ]:
def prime_list(n):
return [p for p in range(3,n) if is_prime(p)]
def is_prime(p):
return all([p%x for x in xrange(2,p)])
print prime_list(100)
In [ ]:
def prime_list(n):
return [p for p in range(3,n) if all([p%x for x in xrange(2,p)])]
print prime_list(100)
reduce(sum, [2,4,6])
-> sum(2, sum(4, 6)) -> sum(2,10) -> 12
In [ ]:
def prime_list(n):
return [p for p in range(3,n) if is_prime(p)]
def is_prime(p):
return all([p%x for x in range(2,p)])
print prime_list(100)
In [ ]:
def prime_list(n):
def add(a,b):
return a+b
return reduce(add, filter(is_prime, range(3,n)))
def is_prime(p):
def not_div(x):
return p%x>0
return all(map(not_div,range(2,p)))
print prime_list(100)
In [ ]:
def my_list(n):
l = []
i = 0
while i<n:
l.append(i)
i+=1
return l
print my_list(10)
In [ ]:
def my_list(n):
l = []
for i in range(n):
l.append(i)
return l
print my_list(10)
In [ ]:
def my_list(n):
return [x for x in range(n)]
print my_list(10)
In [ ]:
def my_list(n):
return range(n)
print my_list(10)
In [ ]:
my_list = range
print my_list(10)
In [ ]:
def my_generator(n):
i = 0
while i<n:
yield(i)
i+=1
print my_generator(10)
In [ ]:
for i in my_generator(5):
print i
In [ ]:
def my_generator(n):
for in xrange(n):
yield(i)
print my_generator(10)
In [ ]:
def my_generator(n):
return (x for x in xrange(n))
print my_generator(10)
In [ ]:
my_generator = xrange
print my_generator(10)
In [ ]:
def test(range_, exp=30):
for x in range_(2**exp):
if x==3:
break
In [ ]:
#test with generator
%timeit test(xrange)
In [ ]:
#test with list
%timeit test(range,30)
In [ ]:
def pow(x,e=2):
return x**e
print pow(4)
In [ ]:
#refactor
pow = lambda x: x**2
print pow(4)
In [ ]:
#refactor
print (lambda x: x**2)(5)
In [ ]:
#example
print map(lambda x: x**2, range(4))
Modify generator_map
to be a generator version of the of the built-in map
function
In [ ]:
def generator_map(f,seq):
return map(f,seq) #Modify this line
#Test
assert not isinstance(generator_map(lambda x : x**2, [1,2,3,4]), list)
for a,b in zip(generator_map(lambda x : x**2, [1,2,3,4]), [1,4,9,16]):
assert a==b
assert a==b==16
print "Yeah!"
In order to benefit from generator_map
being a generator, is_primes
must return as soon as any number that is divisible by x is found.
is_prime_any
to use any
instead of all
In [ ]:
def is_prime_all(p):
return all(map(lambda x : p%x, xrange(2,p)))
def is_prime_any(p,map_=map):
return all(map_(lambda x : p%x, xrange(2,p))) #Modify this line
for p in range(3,100):
for map_ in [map, generator_map]:
assert is_prime_all(p)==is_prime_any(p, map_)
is_prime_generator2
to be a lambda function analougue to is_prime_generator2
In [ ]:
def prime_list(n, is_prime_func=is_prime_all):
return map(is_prime_func, range(3,n))
def is_prime_generator1(p):
return is_prime_any(p, generator_map)
#Your generator lambda function
is_prime_generator2 = lambda p ...
assert prime_list(100)==prime_list(100, is_prime_generator1)
assert prime_list(100)==prime_list(100, is_prime_generator2)
In [ ]:
n=1000
%timeit prime_list(n)
%timeit prime_list(n, lambda p : is_prime_any(p, generator_map))
Organize code in classes
Pro:
Inherritance: Extend and change existing classes (instead of copy/paste/modify = code duplication = Bad!!!)
Testing may be easy
Con:
In [1]:
class Prime(object):
def __init__(self, n, last_number):
self.n = n
self.last_number = last_number
def last_prime(self):
return self.n
def __str__(self):
return "I am: %2d, prime: %s,\tprev prime: %s" % (self.n,
bool(isinstance(self, Prime)),
self.last_number.last_prime())
class NonPrime(object):
def __init__(self, n, last_number):
self.n = n
self.last_number = last_number
def last_prime(self):
return self.last_number.last_prime()
def __str__(self):
return "I am: %2d, prime: %s,\tprev prime: %s" % (self.n,
bool(isinstance(self, Prime)),
self.last_number.last_prime())
class Two(object):
def __init__(self):
self.n = 2
self.last_number = None
def last_prime(self):
return self.n
def __str__(self):
return "I am: 2, prime: True,\tprev prime: --"
is_prime = lambda n : all([n%x for x in range(2,n)])
numbers = [Two()]
for n in range(3,13):
if is_prime(n):
numbers.append(Prime(n, numbers[-1]))
else:
numbers.append(NonPrime(n, numbers[-1]))
for n in numbers:
print n
In [2]:
#refactor
class Number(object):
def __init__(self, n, last_number):
self.n = n
self.last_number = last_number
def info(self, prev_prime):
return "I am: %2d, prime: %s,\tprevious prime: %s" % (self.n,
bool(isinstance(self, Prime)),
prev_prime)
def __str__(self):
return self.info(self.last_number.last_prime())
class Prime(Number):
def last_prime(self):
return self.n
class NonPrime(Number):
def last_prime(self):
return self.last_number.last_prime()
class Two(Prime):
def __init__(self):
Prime.__init__(self, 2,None)
def __str__(self):
return self.info("--")
is_prime = lambda n : all([n%x for x in range(2,n)])
numbers = [Two()]
for n in range(3,13):
if is_prime(n):
numbers.append(Prime(n, numbers[-1]))
else:
numbers.append(NonPrime(n, numbers[-1]))
for n in numbers:
print n
In [ ]:
Make a class MagicInt
that satisfies the assert statements, i.e:
prime
that returns True
the if it is a prime.prime
property manually
In [ ]:
class MagicInt(...
#Do not modify code below
two = MagicInt(2)
m127 = MagicInt(127)
# a int
assert isinstance(two, int)
# 2 + 2 = 5
assert two + two == 5
assert two + 3 == 5
#Result of addition is also a MInt object
assert isinstance(two + two, MagicInt)
assert isinstance(two + 3, MagicInt)
# len() return the number of digits
assert len(two)==1
assert len(m127) == 3
assert len(MagicInt(-127)) == 3
# property prime that returns True the if it is a prime
assert m127.prime
assert (two+m127).prime==False
# Allow the user to set the 'prime' property manually
m127.prime = False
assert m127.prime==False
print "Yeah!!! All asserts satisfied"