1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
| """ A 2-dimensional vector class
>>> v1 = Vector2d(3, 4) >>> print(v1.x, v1.y) 3.0 4.0 >>> x, y = v1 >>> x, y (3.0, 4.0) >>> v1 Vector2d(3.0, 4.0) >>> v1_clone = eval(repr(v1)) >>> v1 == v1_clone True >>> print(v1) (3.0, 4.0) >>> octets = bytes(v1) >>> octets b'd\\x00\\x00\\x00\\x00\\x00\\x00\\x08@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@' >>> abs(v1) 5.0 >>> bool(v1), bool(Vector2d(0, 0)) (True, False)
Test of ``.frombytes()`` class method:
>>> v1_clone = Vector2d.frombytes(bytes(v1)) >>> v1_clone Vector2d(3.0, 4.0) >>> v1 == v1_clone True
Tests of ``format()`` with Cartesian coordinates:
>>> format(v1) '(3.0, 4.0)' >>> format(v1, '.2f') '(3.00, 4.00)' >>> format(v1, '.3e') '(3.000e+00, 4.000e+00)'
Tests of the ``angle`` method::
>>> Vector2d(0, 0).angle() 0.0 >>> Vector2d(1, 0).angle() 0.0 >>> epsilon = 10**-8 >>> abs(Vector2d(0, 1).angle() - math.pi/2) < epsilon True >>> abs(Vector2d(1, 1).angle() - math.pi/4) < epsilon True
Tests of ``format()`` with polar coordinates:
>>> format(Vector2d(1, 1), 'p') # doctest:+ELLIPSIS '<1.414213..., 0.785398...>' >>> format(Vector2d(1, 1), '.3ep') '<1.414e+00, 7.854e-01>' >>> format(Vector2d(1, 1), '0.5fp') '<1.41421, 0.78540>'
Tests of `x` and `y` read-only properties:
>>> v1.x, v1.y (3.0, 4.0) >>> v1.x = 123 Traceback (most recent call last): ... AttributeError: can't set attribute
Tests of hashing:
>>> v1 = Vector2d(3, 4) >>> v2 = Vector2d(3.1, 4.2) >>> hash(v1), hash(v2) (7, 384307168202284039) >>> len(set([v1, v2])) 2
# END VECTOR2D_V3_DEMO
"""
from array import array import math
class Vector2d: __slots__ = ('__x', '__y')
typecode = 'd'
def __init__(self, x, y): self.__x = float(x) self.__y = float(y) @property def x(self): return self.__x @property def y(self): return self.__y def __iter__(self): return (i for i in (self.x, self.y)) def __repr__(self): class_name = type(self).__name__ 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 __hash__(self): return hash(self.x) ^ hash(self.y)
def __abs__(self): return math.hypot(self.x, self.y)
def __bool__(self): return bool(abs(self))
def angle(self): return math.atan2(self.y, self.x)
def __format__(self, fmt_spec=''): if fmt_spec.endswith('p'): fmt_spec = fmt_spec[:-1] coords = (abs(self), self.angle()) outer_fmt = '<{}, {}>' else: coords = self outer_fmt = '({}, {})' components = (format(c, fmt_spec) for c in coords) return outer_fmt.format(*components)
@classmethod def frombytes(cls, octets): typecode = chr(octets[0]) memv = memoryview(octets[1:]).cast(typecode) return cls(*memv)
|