class, templates
from array import array
import math
class Vector2d:
typecode='d'
def __init__(self,x,y):
self.__x=float(x)
self.__y=float(y)
@property #@property decorator marks the getter method of a property
def x(self):
return self.__x
@property
def y(self):
return self.__y
def __hash__(self):
'''
To make a Vector2d hashable we must implement __hash__ (__eq__ is also required).
We also need to make vector instances immutable.
'''
return hash(self.x)^hash(self.y)
def __iter__(self):
'''
__iter__ makes a Vector2d iterale; this is what makes unpacking work, e.g, x,y=my_vector,
*self, tuple(self) and so on.
'''
return (i for i in (self.x,self.y))
def __repr__(self):
class_name=type(self).__name__ #trick: type().__name__
#_repr__builds a string by interpolating the components with {!r} to get their repr
# *self feeds the x and y components to format
return '{}({!r},{!r})'.format(class_name,*self)
def __str__(self):
return str(tuple(self))
def __bytes__(self):
return (bytes([ord(self.typecode)]))+bytes(array(self.typecode,self))
def __eq__(self, other):
return tuple(self)==tuple(other)
def __abs__(self):
return math.hypot(self.x,self.y)
def __bool__(self):
return bool(abs(self))
@classmethod
def frombytes(cls,octets):
typecode=chr(octets[0])
memv=memoryview(octets[1:].cast(typecode))
return cls(*memv)
def __format__(self, format_spec=''):
components=(format(c,format_spec) for c in self)
return '({},{})'.format(*components)