Created
January 14, 2015 00:12
-
-
Save kcsaff/50b918b1c12c95c8500e to your computer and use it in GitHub Desktop.
Simple Python Vector class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import operator | |
class Vector(object): | |
def __init__(self, data, typ=None, copy=True): | |
self._type = typ | |
if isinstance(data, int): | |
self.data = [self._type() for _ in range(data)] | |
elif copy: | |
self.data = list(data) # copy the data | |
else: # This is (probably) a slice or copy is unnecessary for some other reason | |
self.data = data | |
if self._type is None: | |
self._type = type(self.data[0]) | |
def apply(self, fun): | |
""" | |
Equivalent to `Vector(fun(x) for x in self)` | |
>>> Vector([{1,2,3}, {4,5}]).apply(len) | |
Vector([3, 2]) | |
""" | |
return Vector(fun(x) for x in self) | |
def __iter__(self): | |
return iter(self.data) | |
def __getitem__(self, key): | |
if isinstance(key, slice): | |
return self.__class__(self.data[key], self._type, copy=False) | |
else: | |
return self.data[key] | |
def __len__(self): | |
""" | |
Return length of data. | |
>>> len(Vector([{1,2,3}, {5}, {}, {}])) | |
4 | |
""" | |
return len(self.data) | |
def shift(self, amount): | |
""" | |
Shift all users left (for positive amount) or right (for negative amount), while leaving the length unchanged. | |
Key to remembering is that v.shift(a)[b] == v[a+b] for b, a+b positive | |
>>> Vector([{1,2}, {3}, {4, 5}]).shift(-1) | |
Vector([set(), {1, 2}, {3}]) | |
>>> Vector([{1,2}, {3}, {4, 5}]).shift(+1) | |
Vector([{3}, {4, 5}, set()]) | |
""" | |
if amount < 0: | |
data = [self._type() for _ in range(abs(amount))] + self.data[:amount] | |
else: | |
data = self.data[amount:] + [self._type() for _ in range(abs(amount))] | |
return self.__class__(data, self._type, copy=False) | |
def __repr__(self): | |
""" | |
Return `repr` of this object. | |
>>> repr(Vector([{1,2}, {3}, {4, 5}])) | |
'Vector([{1, 2}, {3}, {4, 5}])' | |
""" | |
return '{cls}({data})'.format(cls=self.__class__.__name__, data=self.data) | |
# Operators used for the calculator function | |
def __pos__(self): | |
return self.apply(operator.pos) | |
def __neg__(self): | |
return self.apply(operator.neg) | |
def __and__(self, other): | |
""" | |
Return intersection of my items with other's items. | |
>>> Vector([{1,2,3}, {4,5}, {1,2}]) & Vector([{2,5}, {1,4}, {7,8}]) | |
Vector([{2}, {4}, set()]) | |
""" | |
return self._apply_function2(other, operator.and_) | |
def __or__(self, other): | |
"""Return union of my users with other users.""" | |
return self._apply_function2(other, operator.or_) | |
def __xor__(self, other): | |
"""Return exclusive or of my users with other users.""" | |
return self._apply_function2(other, operator.xor) | |
def __add__(self, other): | |
"""Add one vector to another.""" | |
return self._apply_function2(other, operator.add) | |
def __sub__(self, other): | |
"""Subtract one vector from another.""" | |
return self._apply_function2(other, operator.sub) | |
def __mul__(self, other): | |
"""Multiply one vector by another. | |
>>> Vector([1,2,3]) * Vector([2,2,0]) | |
Vector([2, 4, 0]) | |
>>> Vector([1,2,3]) * [2,2,0] | |
Vector([2, 4, 0]) | |
>>> Vector([1,2,3]) * 2 | |
Vector([2, 4, 6]) | |
""" | |
return self._apply_function2(other, operator.mul) | |
def __truediv__(self, other): | |
"""Return vector of my sizes divided by other object.""" | |
return self._apply_function2(other, (lambda x, y: operator.truediv(x,y) if y else None)) | |
def _apply_function2(self, other, fun): | |
try: | |
otherlen = len(other) | |
except TypeError: # No length, must be scalar | |
return Vector( | |
fun(self.data[i], other) | |
if self.data[i] is not None | |
else None | |
for i in range(len(self)) | |
) | |
else: | |
if len(self) != len(other): | |
raise Exception('Vector lengths not the same.') | |
return Vector( | |
fun(self.data[i], other[i]) | |
if self.data[i] is not None and other[i] is not None | |
else None | |
for i in range(len(self)) | |
) | |
def _return_same_thing(x): | |
return x | |
if __name__ == '__main__': | |
import doctest | |
doctest.testmod() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment