patternpythonModerate
What's the optimal 'pythonic' way to make dot product of two lists of numbers?
Viewed 0 times
pythonictheoptimalwhatnumbersmakewaydotproducttwo
Problem
I just filled in the first assignment on course which involves learning Python. The assignment was to make vector class which supports scalar multiplication through operator overloading.
The instructions included these constains:
This is what I have sent:
The homework was OK, but the validation system is bragging that their implementation is faster:
Message: module file vectors.py found
Result ok
Your elapsed time for 10,000 trials, vectors length 300: 0.67
The instructions included these constains:
- There will be one class called
MyVector
- Nothing will be imported in file within that file which contains the class
- The class will accept one argument in constructor, which must be list of numbers
- The class will have two methods:
get_vectorwhich returns list of numbers of the vector
__mul__(overloaded*operator) which performs scalar multiplication of two vectors
This is what I have sent:
class MyVector:
"""Vector class"""
coordinates = None
def __init__(self, coordinates):
if not isinstance(coordinates, list):
raise TypeError("Coordinates of vector must me single dimensional array.")
self.coordinates = coordinates
def f(self):
return 'hello world'
def get_vector(self):
return self.coordinates
def dimensions(self):
return len(self.coordinates)
def __mul__(self,other):
if other.dimensions() != self.dimensions():
raise ValueError("Number of dimensions of multiplied vectors must be equal.")
tmp = 0
for index in range(self.dimensions()):
tmp += self.coordinates[index] * other.coordinates[index]
return tmp
''' Just a testing section recommended in the assignment '''
if __name__ == "__main__":
vec1 = MyVector([1,2,5,5,5]) # vektory mohou byt i jine dimenze nez 3!
vec2 = MyVector([1,2,5,5,5])
print(vec1.get_vector()) # Test getting the list of items
dot_product = vec1*vec2 # Multiplication test
print(dot_product)The homework was OK, but the validation system is bragging that their implementation is faster:
Message: module file vectors.py found
Result ok
Your elapsed time for 10,000 trials, vectors length 300: 0.67
Solution
The most "pythonic" way of doing this makes use of the
I suggest making use of the REPL (interactive shell) to learn about them, here is an example REPL session that you can read explaining
Other points
-
Tests should be automatic and NOT rely on you manually checking that wha is printed is right. This manual method will become too time consuming very soon.
-
-
-
Use
sum and zip built-ins:def __mul__(self,other):
if other.dimensions() != self.dimensions():
raise ValueError("Number of dimensions of multiplied vectors must be equal.")
return sum(a * b for a, b in zip(self.coordinates, other.coordinates))I suggest making use of the REPL (interactive shell) to learn about them, here is an example REPL session that you can read explaining
zip and sum:>>> x = [1, 4, 8]
>>> sum(x)
13
>>> y = [6, 1, 0]
>>> zip(x, y)
>>> list(_) # `_` means previous value
[(1, 6), (4, 1), (8, 0)]
>>> help(zip)
Help on class zip in module builtins:
class zip(object)
| zip(iter1 [,iter2 [...]]) --> zip object
|
| Return a zip object whose .__next__() method returns a tuple where
| the i-th element comes from the i-th iterable argument. The .__next__()
| method continues until the shortest iterable in the argument sequence
| is exhausted and then it raises StopIteration.
|
| Methods defined here:
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __iter__(self, /)
| Implement iter(self).
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
|
| __next__(self, /)
| Implement next(self).
|
| __reduce__(...)
| Return state information for pickling.
>>> help(sum)
Help on built-in function sum in module builtins:
sum(...)
sum(iterable[, start]) -> value
Return the sum of an iterable of numbers (NOT strings) plus the value
of parameter 'start' (which defaults to 0). When the iterable is
empty, return start.
>>> zip( (1,2,3), "abc" )
>>> list(_)
[(1, 'a'), (2, 'b'), (3, 'c')]Other points
-
Tests should be automatic and NOT rely on you manually checking that wha is printed is right. This manual method will become too time consuming very soon.
-
f makes no sense (probably it is a leftover from a previous assignment). Please remove it.-
get methods are discouraged in Python, accessing the items directly is very simple anyway.-
Use
@property to give convenient call sintax in dimensions(self) or remove this property completely as you can just call len(vector.coordinates) very easily.Code Snippets
def __mul__(self,other):
if other.dimensions() != self.dimensions():
raise ValueError("Number of dimensions of multiplied vectors must be equal.")
return sum(a * b for a, b in zip(self.coordinates, other.coordinates))>>> x = [1, 4, 8]
>>> sum(x)
13
>>> y = [6, 1, 0]
>>> zip(x, y)
<zip object at 0x7f51da3db5c8>
>>> list(_) # `_` means previous value
[(1, 6), (4, 1), (8, 0)]
>>> help(zip)
Help on class zip in module builtins:
class zip(object)
| zip(iter1 [,iter2 [...]]) --> zip object
|
| Return a zip object whose .__next__() method returns a tuple where
| the i-th element comes from the i-th iterable argument. The .__next__()
| method continues until the shortest iterable in the argument sequence
| is exhausted and then it raises StopIteration.
|
| Methods defined here:
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __iter__(self, /)
| Implement iter(self).
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
|
| __next__(self, /)
| Implement next(self).
|
| __reduce__(...)
| Return state information for pickling.
>>> help(sum)
Help on built-in function sum in module builtins:
sum(...)
sum(iterable[, start]) -> value
Return the sum of an iterable of numbers (NOT strings) plus the value
of parameter 'start' (which defaults to 0). When the iterable is
empty, return start.
>>> zip( (1,2,3), "abc" )
<zip object at 0x7f51dba79648>
>>> list(_)
[(1, 'a'), (2, 'b'), (3, 'c')]Context
StackExchange Code Review Q#143203, answer score: 14
Revisions (0)
No revisions yet.