Skip to content

Instantly share code, notes, and snippets.

@rldotai
Last active December 15, 2016 17:58
Show Gist options
  • Save rldotai/0b0e56c4dfb17cde00f2 to your computer and use it in GitHub Desktop.
Save rldotai/0b0e56c4dfb17cde00f2 to your computer and use it in GitHub Desktop.
Pure Python Vector class
"""
A simple implementation of vectors in Python modelled after tuples, but having
altered some of the operations to be closer to vector arithmetic.
It targets Python 3.5+ in order to support __matmul__, allowing for dot
products, which I have heard are important in linear algebra.
We check for whether it is operating on a number in order to implement
broadcasting; otherwise it performs the operations elementwise.
We also use `zip_longest` because it performs an implicit check for sequences
of unequal length; it pads the iteration with `None`, which will raise an error
during arithmetic operations.
"""
from itertools import zip_longest
from numbers import Number
from operator import add, floordiv, mul, pow, sub, truediv
class Vector(tuple):
def __abs__(self):
return Vector(abs(x) for x in self)
def __add__(self, other):
if isinstance(other, Number):
return Vector(i + other for i in self)
return Vector(add(a, b) for a, b in zip_longest(self, other))
def __floordiv__(self, other):
if isinstance(other, Number):
return Vector(i // other for i in self)
return Vector(floordiv(a, b) for a, b in zip_longest(self, other))
def __matmul__(self, other):
return sum(mul(a, b) for a, b in zip_longest(self, other))
def __mul__(self, other):
if isinstance(other, Number):
return Vector(i * other for i in self)
return Vector(mul(a, b) for a, b in zip_longest(self, other))
def __neg__(self):
return Vector(-x for x in self)
def __pow__(self, other):
if isinstance(other, Number):
return Vector(i**other for i in self)
return Vector(pow(a, b) for a, b in zip_longest(self, other))
def __sub__(self, other):
if isinstance(other, Number):
return Vector(i - other for i in self)
return Vector(sub(a, b) for a, b in zip_longest(self, other))
def __radd__(self, other):
if isinstance(other, Number):
return Vector(i + other for i in self)
return Vector(add(a, b) for a, b in zip_longest(self, other))
def __rfloordiv__(self, other):
if isinstance(other, Number):
return Vector(i // other for i in self)
return Vector(floordiv(a, b) for a, b in zip_longest(self, other))
def __rmatmul__(self, other):
return sum(mul(a, b) for a, b in zip_longest(self, other))
def __rmul__(self, other):
if isinstance(other, Number):
return Vector(i * other for i in self)
return Vector(mul(a, b) for a, b in zip_longest(self, other))
def __rpow__(self, other):
if isinstance(other, Number):
return Vector(i**other for i in self)
return Vector(pow(a, b) for a, b in zip_longest(self, other))
def __rsub__(self, other):
if isinstance(other, Number):
return Vector(i - other for i in self)
return Vector(sub(a, b) for a, b in zip_longest(self, other))
def __rtruediv__(self, other):
if isinstance(other, Number):
return Vector(i / other for i in self)
return Vector(truediv(a, b) for a, b in zip_longest(self, other))
def __truediv__(self, other):
if isinstance(other, Number):
return Vector(i / other for i in self)
return Vector(truediv(a, b) for a, b in zip_longest(self, other))
@susca
Copy link

susca commented Dec 15, 2016

Hello,

looks good, would you add a license, so that I can (hopefully) use it in my code?
Thank you.

ps my code is MIT licenced.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment