diff --git a/classes/vector2d_v0.py b/classes/vector2d_v0.py index ce21628..5024f0f 100644 --- a/classes/vector2d_v0.py +++ b/classes/vector2d_v0.py @@ -4,22 +4,24 @@ A 2-dimensional vector class # BEGIN VECTOR2D_V0_DEMO >>> v1 = Vector2d(3, 4) - >>> x, y = v1 #<1> + >>> print(v1.x, v1.y) # <1> + 3.0 4.0 + >>> x, y = v1 # <2> >>> x, y (3.0, 4.0) - >>> v1 #<2> + >>> v1 # <3> Vector2d(3.0, 4.0) - >>> v1_clone = eval(repr(v1)) #<3> - >>> v1 == v1_clone + >>> v1_clone = eval(repr(v1)) # <4> + >>> v1 == v1_clone # <5> True - >>> print(v1) #<4> + >>> print(v1) # <6> (3.0, 4.0) - >>> octets = bytes(v1) #<5> + >>> octets = bytes(v1) # <7> >>> octets - b'\\x00\\x00\\x00\\x00\\x00\\x00\\x08@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@' - >>> abs(v1) #<6> + b'd\\x00\\x00\\x00\\x00\\x00\\x00\\x08@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@' + >>> abs(v1) # <8> 5.0 - >>> bool(v1), bool(Vector2d(0, 0)) #<7> + >>> bool(v1), bool(Vector2d(0, 0)) # <9> (True, False) # END VECTOR2D_V0_DEMO @@ -41,20 +43,22 @@ class Vector2d: return (i for i in (self.x, self.y)) # <3> def __repr__(self): - return 'Vector2d({!r}, {!r})'.format(*self) # <4> + class_name = type(self).__name__ + return '{}({!r}, {!r})'.format(class_name, *self) # <4> def __str__(self): return str(tuple(self)) # <5> def __bytes__(self): - return bytes(array(Vector2d.typecode, self)) # <6> + return (bytes([ord(self.typecode)]) + # <6> + bytes(array(self.typecode, self))) # <7> def __eq__(self, other): - return tuple(self) == tuple(other) # <7> + return tuple(self) == tuple(other) # <8> def __abs__(self): - return math.hypot(self.x, self.y) + return math.hypot(self.x, self.y) # <9> def __bool__(self): - return bool(abs(self)) # <8> + return bool(abs(self)) # <10> # END VECTOR2D_V0 diff --git a/classes/vector2d_v1.py b/classes/vector2d_v1.py index ac4adfe..6484efd 100644 --- a/classes/vector2d_v1.py +++ b/classes/vector2d_v1.py @@ -2,25 +2,28 @@ A 2-dimensional vector class >>> v1 = Vector2d(3, 4) - >>> x, y = v1 #<1> + >>> print(v1.x, v1.y) + 3.0 4.0 + >>> x, y = v1 >>> x, y (3.0, 4.0) - >>> v1 #<2> + >>> v1 Vector2d(3.0, 4.0) - >>> v1_clone = eval(repr(v1)) #<3> + >>> v1_clone = eval(repr(v1)) >>> v1 == v1_clone True - >>> print(v1) #<4> + >>> print(v1) (3.0, 4.0) - >>> octets = bytes(v1) #<5> + >>> octets = bytes(v1) >>> octets - b'\\x00\\x00\\x00\\x00\\x00\\x00\\x08@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@' - >>> abs(v1) #<6> + 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)) #<7> + >>> bool(v1), bool(Vector2d(0, 0)) (True, False) -Test of .frombytes() class method: + +Test of ``.frombytes()`` class method: >>> v1_clone = Vector2d.frombytes(bytes(v1)) >>> v1_clone @@ -28,21 +31,6 @@ Test of .frombytes() class method: >>> v1 == v1_clone True -So far, Vector2d instances are unhashable: - -# BEGIN VECTOR2D_V1_UNHASHABLE_DEMO - >>> v1 = Vector2d(3, 4) - >>> hash(v1) - Traceback (most recent call last): - ... - TypeError: unhashable type: 'Vector2d' - >>> set([v1]) - Traceback (most recent call last): - ... - TypeError: unhashable type: 'Vector2d' - -# END VECTOR2D_V1_UNHASHABLE_DEMO - """ from array import array @@ -60,13 +48,15 @@ class Vector2d: return (i for i in (self.x, self.y)) def __repr__(self): - return 'Vector2d({!r}, {!r})'.format(*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(array(Vector2d.typecode, self)) + return (bytes([ord(self.typecode)]) + + bytes(array(self.typecode, self))) def __eq__(self, other): return tuple(self) == tuple(other) @@ -80,6 +70,7 @@ class Vector2d: # BEGIN VECTOR2D_V1 @classmethod # <1> def frombytes(cls, octets): # <2> - memv = memoryview(octets).cast(cls.typecode) # <3> - return cls(*memv) # <4> + typecode = chr(octets[0]) # <3> + memv = memoryview(octets[1:]).cast(typecode) # <4> + return cls(*memv) # <5> # END VECTOR2D_V1 diff --git a/classes/vector2d_v2.py b/classes/vector2d_v2.py index 6233a0d..2a9dcf5 100644 --- a/classes/vector2d_v2.py +++ b/classes/vector2d_v2.py @@ -2,6 +2,8 @@ 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) @@ -14,7 +16,7 @@ A 2-dimensional vector class (3.0, 4.0) >>> octets = bytes(v1) >>> octets - b'\\x00\\x00\\x00\\x00\\x00\\x00\\x08@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@' + 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)) @@ -80,13 +82,15 @@ class Vector2d: return (i for i in (self.x, self.y)) def __repr__(self): - return 'Vector2d({!r}, {!r})'.format(*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(array(Vector2d.typecode, self)) + return (bytes([ord(self.typecode)]) + + bytes(array(self.typecode, self))) def __eq__(self, other): return tuple(self) == tuple(other) @@ -113,6 +117,7 @@ class Vector2d: @classmethod def frombytes(cls, octets): - memv = memoryview(octets).cast(cls.typecode) + typecode = chr(octets[0]) + memv = memoryview(octets[1:]).cast(typecode) return cls(*memv) # END VECTOR2D_V2 diff --git a/classes/vector2d_v2_fmt_snippet.py b/classes/vector2d_v2_fmt_snippet.py index ff895cb..3574a37 100644 --- a/classes/vector2d_v2_fmt_snippet.py +++ b/classes/vector2d_v2_fmt_snippet.py @@ -79,7 +79,8 @@ class Vector2d: return (i for i in (self.x, self.y)) def __repr__(self): - return 'Vector2d({!r}, {!r})'.format(*self) + class_name = type(self).__name__ + return '{}({!r}, {!r})'.format(class_name, *self) def __str__(self): return str(tuple(self)) diff --git a/classes/vector2d_v3.py b/classes/vector2d_v3.py index 66b09ed..5812dcf 100644 --- a/classes/vector2d_v3.py +++ b/classes/vector2d_v3.py @@ -2,26 +2,28 @@ A 2-dimensional vector class >>> v1 = Vector2d(3, 4) - >>> x, y = v1 #<1> + >>> print(v1.x, v1.y) + 3.0 4.0 + >>> x, y = v1 >>> x, y (3.0, 4.0) - >>> v1 #<2> + >>> v1 Vector2d(3.0, 4.0) - >>> v1_clone = eval(repr(v1)) #<3> + >>> v1_clone = eval(repr(v1)) >>> v1 == v1_clone True - >>> print(v1) #<4> + >>> print(v1) (3.0, 4.0) - >>> octets = bytes(v1) #<5> + >>> octets = bytes(v1) >>> octets - b'\\x00\\x00\\x00\\x00\\x00\\x00\\x08@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@' - >>> abs(v1) #<6> + 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)) #<7> + >>> bool(v1), bool(Vector2d(0, 0)) (True, False) -Test of .frombytes() class method: +Test of ``.frombytes()`` class method: >>> v1_clone = Vector2d.frombytes(bytes(v1)) >>> v1_clone @@ -62,8 +64,8 @@ Tests of ``format()`` with polar coordinates: >>> format(Vector2d(1, 1), '0.5fp') '<1.41421, 0.78540>' -# BEGIN VECTOR2D_V3_DEMO -Test of `x` and `y` read-only properties: + +Tests of `x` and `y` read-only properties: >>> v1.x, v1.y (3.0, 4.0) @@ -72,9 +74,8 @@ Test of `x` and `y` read-only properties: ... AttributeError: can't set attribute -# END VECTOR2D_V3_HASH_DEMO -# BEGIN VECTOR2D_V3_HASH_DEMO +Tests of hashing: >>> v1 = Vector2d(3, 4) >>> v2 = Vector2d(3.1, 4.2) @@ -83,52 +84,45 @@ Test of `x` and `y` read-only properties: >>> len(set([v1, v2])) 2 -# END VECTOR2D_V3_DEMO - - """ from array import array import math -# BEGIN VECTOR2D_V3 class Vector2d: typecode = 'd' def __init__(self, x, y): - self.__x = float(x) # <1> + self.__x = float(x) self.__y = float(y) - @property # <2> - def x(self): # <3> - return self.__x # <4> + @property + def x(self): + return self.__x - @property # <5> + @property def y(self): return self.__y def __iter__(self): - return (i for i in (self.x, self.y)) # <6> - - # remaining methods follow (omitted in book listing) -# END VECTOR2D_V3 + return (i for i in (self.x, self.y)) def __repr__(self): - return 'Vector2d({!r}, {!r})'.format(*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(array(Vector2d.typecode, self)) + return (bytes([ord(self.typecode)]) + + bytes(array(self.typecode, self))) def __eq__(self, other): return tuple(self) == tuple(other) -# BEGIN VECTOR_V3_HASH def __hash__(self): return hash(self.x) ^ hash(self.y) -# END VECTOR_V3_HASH def __abs__(self): return math.hypot(self.x, self.y) @@ -152,5 +146,6 @@ class Vector2d: @classmethod def frombytes(cls, octets): - memv = memoryview(octets).cast(cls.typecode) + typecode = chr(octets[0]) + memv = memoryview(octets[1:]).cast(typecode) return cls(*memv) diff --git a/classes/vector2d_v3_slots.py b/classes/vector2d_v3_slots.py index 1a6d21d..a9d700d 100644 --- a/classes/vector2d_v3_slots.py +++ b/classes/vector2d_v3_slots.py @@ -2,26 +2,28 @@ A 2-dimensional vector class >>> v1 = Vector2d(3, 4) - >>> x, y = v1 #<1> + >>> print(v1.x, v1.y) + 3.0 4.0 + >>> x, y = v1 >>> x, y (3.0, 4.0) - >>> v1 #<2> + >>> v1 Vector2d(3.0, 4.0) - >>> v1_clone = eval(repr(v1)) #<3> + >>> v1_clone = eval(repr(v1)) >>> v1 == v1_clone True - >>> print(v1) #<4> + >>> print(v1) (3.0, 4.0) - >>> octets = bytes(v1) #<5> + >>> octets = bytes(v1) >>> octets - b'\\x00\\x00\\x00\\x00\\x00\\x00\\x08@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@' - >>> abs(v1) #<6> + 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)) #<7> + >>> bool(v1), bool(Vector2d(0, 0)) (True, False) -Test of .frombytes() class method: +Test of ``.frombytes()`` class method: >>> v1_clone = Vector2d.frombytes(bytes(v1)) >>> v1_clone @@ -62,8 +64,8 @@ Tests of ``format()`` with polar coordinates: >>> format(Vector2d(1, 1), '0.5fp') '<1.41421, 0.78540>' -# BEGIN VECTOR2D_V3_DEMO -Test of `x` and `y` read-only properties: + +Tests of `x` and `y` read-only properties: >>> v1.x, v1.y (3.0, 4.0) @@ -72,9 +74,7 @@ Test of `x` and `y` read-only properties: ... AttributeError: can't set attribute -# END VECTOR2D_V3_HASH_DEMO - -# BEGIN VECTOR2D_V3_HASH_DEMO +Tests of hashing: >>> v1 = Vector2d(3, 4) >>> v2 = Vector2d(3.1, 4.2) @@ -85,7 +85,6 @@ Test of `x` and `y` read-only properties: # END VECTOR2D_V3_DEMO - """ from array import array @@ -116,21 +115,21 @@ class Vector2d: return (i for i in (self.x, self.y)) def __repr__(self): - return 'Vector2d({!r}, {!r})'.format(*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(array(Vector2d.typecode, self)) + return (bytes([ord(self.typecode)]) + + bytes(array(self.typecode, self))) def __eq__(self, other): return tuple(self) == tuple(other) -# BEGIN VECTOR2D_V3_HASH def __hash__(self): return hash(self.x) ^ hash(self.y) -# END VECTOR2D_V3_HASH def __abs__(self): return math.hypot(self.x, self.y) @@ -154,5 +153,6 @@ class Vector2d: @classmethod def frombytes(cls, octets): - memv = memoryview(octets).cast(cls.typecode) + typecode = chr(octets[0]) + memv = memoryview(octets[1:]).cast(typecode) return cls(*memv)