from functools import wraps
def timefn(fn):
@wraps(fn)
def measure_time(*args, **kwargs):
t1 = time.time()
result = fn(*args, **kwargs)
t2 = time.time()
print ("@timefn:" + fn.func_name + " took " + str(t2 - t1) + " seconds")
return result
return measure_time
@timefn
def calculate_z_serial_purepython(maxiter, zs, cs):
%timeit calc_pure_python(desired_width=1000, max_iterations=300)
or
%%time calc_pure_python(desired_width=1000, max_iterations=300)
In [1]: import pstats
In [2]: p = pstats.Stats("profile.stats")
In [3]: p.sort_stats("cumulative")
Out[3]: <pstats.Stats instance at 0x177dcf8>
In [4]: p.print_stats()
p.print_callers()
p.print_callees() # flip callee around
pip install line_profiler.
kernprof.py -l -v julia1_lineprofiler.py
@profile # add decorator on the function called.
# ex.py
import unittest
@profile
def some_fn(nbr):
return nbr * 2
class TestCase(unittest.TestCase):
def test(self):
result = some_fn(2)
self.assertEquals(result, 4)
$ nosetests ex.py
pip install snakeviz
snakeviz profile.stats
These differences outline the philosophical difference between the two: tuples are for describing multiple properties of one unchanging thing, and lists can be used to store collections of data about completely disparate objects even if we create a list without append (and thus we don’t have the extra headroom introduced by an append operation), it will still be larger in memory than a tuple with the same data
Once a list has been sorted, we can find our desired element using a binary search (Example 3-3), which has an average case complexity of O(log n). It achieves this by first looking at the middle of the list and comparing this value with the desired value. If this midpoint’s value is less than our desired value, then we consider the right half of the list, and we continue halving the list like this until the value is found, or until the value is known not to occur in the sorted list. As a result, we do not need to read all values in the list, as was necessary for the linear search; instead, we only read a small subset of them
Sets and dictionaries are ideal data structures to be used when your data has no intrinsic order, but does have a unique object that can be used to reference it (the reference object is normally a string, but can be any hashable type). This reference object is called the “key,” while the data is the “value.”
a set is simply a collection of unique keys
creating hash function
wdict = {}
for word in words:
try:
wdict[word] += 1
except KeyError:
wdict[word] = 1
wdict = {}
get = wdict.get
for word in words:
wdict[word] = get(word, 0) + 1
searching local variables first
global variable
__builtin__
Since xrange already returns an iterator, calling iter on it is a trivial operation, and it simply returns the original object (so type(xrange(1,10)) == type(iter(xrange(1,10)))). However, since range returns a list, we must create a new object, a list iterator, that will iterate over all values in the list.
def fibonacci():
i, j = 0, 1
while True:
yield j
i, j = j, i + j
def fibonacci_transform():
count = 0
for f in fibonacci():
if f > 5000:
break
if f % 2:
count += 1
return count