Vector methods to be created:
In [35]:
class vector_math:
'''
This is the base class for vector math - which allows for initialization with two vectors.
'''
def __init__(self, vectors = [[1,2,2],[3,4,3]]):
self.vect1 = vectors[0]
self.vect2 = vectors[1]
def set_vects(self, vectors):
self.vect1 = vectors[0]
self.vect2 = vectors[1]
def sum_vects(self):
return [x + y for x, y in zip(self.vect1, self.vect2)]
def sub_vects(self):
# default should be [-2,-2,-1]
return [x - y for x, y in zip(self.vect1, self.vect2)]
# Can expand out to for x, y in zip: ... to show what it and sum do
def multi_vects(self):
#default should be [3,8,6]
return [x * y for x, y in zip(self.vect1, self.vect2)]
def multi_scalar(self, scalar, vect):
return [e * scalar for e in vect]
# Show difference between just element * number and using tuple from zip()
def multi_scalar_l(self, scalar, vect):
return lambda e: e * scalar, vect
def mean_vects(self):
mean_vect = self.sum_vects()
return self.multi_scalar(1/len(mean_vect), mean_vect)
def dot_product(self):
return sum(self.multi_vects())
vect = vector_math()
sum_vect = vect.sum_vects()
print("Sum of vectors = {}".format(sum_vect))
print("Subtraction of vectors = {}".format(vect.sub_vects()))
print("Product of vectors = {}".format(vect.multi_vects()))
print("Product of Sum of vectors and 2 = {}\n".format(vect.multi_scalar(2, sum_vect)))
# Yep can still use character returns and others in format
print("Average of vectors = {}".format(["{:.2f}".format(e) for e in vect.mean_vects()]))
# Now there are other ways to reduce the decimal places but this was just to show a nested format call
# TODO: Consider adding timeit to show difference between calling multi_scalar directly and calling mean_vect:
#print("Average of vectors through calling scalar = {}".format(
# ["{:.2f}".format(e) for e in vect.multi_scalar(1/len(sum_vect), sum_vect)]))
print("The Dot Product is {}".format(vect.dot_product()))
In [32]:
from math import sqrt
# Using the vect variables showing without functions
sum_of_squares = sum([x * y for x, y in zip(vect.vect1, vect.vect1)])
magnitude = sqrt(sum_of_squares)
distance = sqrt(sum([(x - y) ** 2 for x, y in zip(vect.vect1, vect.vect2)]))
print("Sum of Squares is {}".format(sum_of_squares))
print("Magnitude is {:.2f}".format(magnitude))
print("Distance is {}".format(distance))
Expect to see them throughout code one has to maintain but also understand they are not always the optimal solution
When an iteration is needed to build a composite value, list comprehensions are considered the most readable or understandable way to achieve this. Loops may be used instead if one wants the "side effect" of an interation while functional tools may be used if optimization and code speed is important.
For instance, the above examples could also have been performed with an annoymous lambda or reduce, like:
def multi_scalar(self, vect, scalar):
return lambda e: e * scalar, vect
In this case, the lambda would be faster by a minimal amount and actually have one less function call - which are expensive in Python. This is not always true as the need for an increasing amount of functional methods can change both the speed and amount of function call required. code example is below
In [61]:
import dis
import time
# For instruction - shows disassemble of methods and performs quick time check
vect = [2,3,3,3,4,5,6,6,4,3,2,1,3,4,5,6,4,3,2,1,3,4,5,6,4,3,2]
t1 = time.time()
print("list comp")
dis.dis(compile("[e * 2 for e in vect]", '<stdin>', 'exec'))
d_l = time.time() - t1
print(d_l)
t2 = time.time()
print("\n\n\nlambda")
dis.dis(compile("lambda e: e * 2, vect", '<stdin>', 'exec'))
d_lam = time.time() - t2
print(d_lam)
In [ ]: