patternpythonMinor
Class Vector with Python 3
Viewed 0 times
withclassvectorpython
Problem
Here is a class vector in python 3, for n-dimmensional vectors. Please suggest ways to improve the code as well as fix bugs and errors.
The only rule is not using: numpy, sympy, scipy and so on. Only math, cmath, Rational, Decimal, ... Python 3 default packages..
This code is only for learning to make classes with python 3. I want comments to improve my python learning. For example, a way to improve the
```
# /usr/bin/env python3
# -- coding: utf-8 --
'''
Created on Wed May 7 21:21:21 2014
@author: tobal
'''
from math import sqrt, acos, degrees, radians, cos, sin, fsum, hypot, atan2
class Vector(tuple):
'''"Class to calculate the usual operations with vectors in bi and
tridimensional coordinates. Too with n-dimmensinal.'''
# __slots__=('V') #It's not possible because V is a variable list of param.
def __new__(cls, *V):
'''The new method, we initialize the coordinates of a vector.
You can initialize a vector for example: V = Vector() or
V = Vector(a,b) or V = Vector(v1, v2, ..., vn)'''
if not V:
V = (0, 0)
elif len(V) == 1:
raise ValueError('A vector must have at least 2 coordinates.')
return tuple.__new__(cls, V)
def __add__(self, V):
'''The operator sum overloaded. You can add vectors writing V + W,
where V and W are two vectors.'''
if len(self) != len(V):
raise IndexError('Vectors must have same dimmensions.')
else:
added = tuple(a + b for a, b in zip(self, V))
return Vector(*added)
__radd__ = __add__
def __sub__(self, V):
'''The operator subtraction overloaded. You can subtract vectors writing
V - W, where V and W are two vectors.'''
if len(self) != len(V):
raise IndexError('Vectors must have same dimmensions.')
else:
subtracted = tuple(a - b for a, b in zip(self, V))
return Vector
The only rule is not using: numpy, sympy, scipy and so on. Only math, cmath, Rational, Decimal, ... Python 3 default packages..
This code is only for learning to make classes with python 3. I want comments to improve my python learning. For example, a way to improve the
__init()__ constructor, and so on.```
# /usr/bin/env python3
# -- coding: utf-8 --
'''
Created on Wed May 7 21:21:21 2014
@author: tobal
'''
from math import sqrt, acos, degrees, radians, cos, sin, fsum, hypot, atan2
class Vector(tuple):
'''"Class to calculate the usual operations with vectors in bi and
tridimensional coordinates. Too with n-dimmensinal.'''
# __slots__=('V') #It's not possible because V is a variable list of param.
def __new__(cls, *V):
'''The new method, we initialize the coordinates of a vector.
You can initialize a vector for example: V = Vector() or
V = Vector(a,b) or V = Vector(v1, v2, ..., vn)'''
if not V:
V = (0, 0)
elif len(V) == 1:
raise ValueError('A vector must have at least 2 coordinates.')
return tuple.__new__(cls, V)
def __add__(self, V):
'''The operator sum overloaded. You can add vectors writing V + W,
where V and W are two vectors.'''
if len(self) != len(V):
raise IndexError('Vectors must have same dimmensions.')
else:
added = tuple(a + b for a, b in zip(self, V))
return Vector(*added)
__radd__ = __add__
def __sub__(self, V):
'''The operator subtraction overloaded. You can subtract vectors writing
V - W, where V and W are two vectors.'''
if len(self) != len(V):
raise IndexError('Vectors must have same dimmensions.')
else:
subtracted = tuple(a - b for a, b in zip(self, V))
return Vector
Solution
-
This implementation of
-
In general, when your operator implementation cannot deal with the type of the operand,
-
Your support of operands is in general not consistent, but I’m not sure whether that is relevant to your actual question – you might be aware of this. However, addition and subtraction can work with tuples as operands, while true division can only work with scalars.
-
Using
-
Your implementation of the
-
I have not gone through any method below
-
Refactor your exceptions out, to allow for reuse and consistent error messages. Example:
(alternatively, use a global function instead of
-
There is no point in having constructs such as:
Throwing an exception will disrupt the control flow, so it doesn’t matter whether you have an else branch or just continue your code like this:
The latter improves readability by requiring less indentation depth.
def __sub__(self, V):
'''The operator subtraction overloaded. You can subtract points writing
V - W, where V and W are two vectors.'''
if len(self) != len(V):
raise IndexError('Vectors must have same dimmensions.')
else:
subtracted = tuple(a - b for a, b in zip(self, V))
return Vector(*subtracted)
__rsub__ = __sub__This implementation of
__rsub__ will create wrong results:>>> import Vector
>>> v = Vector.Vector(1, 1)
>>> (0, 0) - v
(1, 1)__rsub__ is called when no working __sub__ implementation is found for the left hand side of an operator. The arguments are then in reverse order with respect to the way __sub__ is called.-
In general, when your operator implementation cannot deal with the type of the operand,
return NotImplemented (not NotImplementedError). Python will then allow the __r*__ operator of the operand to be executed, allowing for more extensibility. For example, if you make a Matrix implementation at some point in the future, it might implement multiplication of vectors from the left by implementing __rmul__, if your __mul__ implementation returns NotImplemented when encountering an unknown type.-
Your support of operands is in general not consistent, but I’m not sure whether that is relevant to your actual question – you might be aware of this. However, addition and subtraction can work with tuples as operands, while true division can only work with scalars.
-
Using
type(1) seems not good to me. If using isinstance at all, you should use the types such as numbers.Number.-
Your implementation of the
__i*__ operators looks as if you accidentially took them for integer operators. Instead, they are supposed to be the implementations of += et al., working with the same operands as +, for example. Please refer to the python documentation on Special Method Names for details of the semantics expected.-
I have not gone through any method below
norm, because I know much of this not certain enough off the top of my head, I however have some more general remarks.-
Refactor your exceptions out, to allow for reuse and consistent error messages. Example:
@staticmethod
def _dimension_mismatch(d1, d2):
raise IndexError(
"Vectors must have same dimensionality (got {} and {})".format(
d1, d2))(alternatively, use a global function instead of
@staticmethod)-
There is no point in having constructs such as:
if a:
raise Something()
else:
do_something()Throwing an exception will disrupt the control flow, so it doesn’t matter whether you have an else branch or just continue your code like this:
if a:
raise Something()
do_something()The latter improves readability by requiring less indentation depth.
Code Snippets
def __sub__(self, V):
'''The operator subtraction overloaded. You can subtract points writing
V - W, where V and W are two vectors.'''
if len(self) != len(V):
raise IndexError('Vectors must have same dimmensions.')
else:
subtracted = tuple(a - b for a, b in zip(self, V))
return Vector(*subtracted)
__rsub__ = __sub__>>> import Vector
>>> v = Vector.Vector(1, 1)
>>> (0, 0) - v
(1, 1)@staticmethod
def _dimension_mismatch(d1, d2):
raise IndexError(
"Vectors must have same dimensionality (got {} and {})".format(
d1, d2))if a:
raise Something()
else:
do_something()if a:
raise Something()
do_something()Context
StackExchange Code Review Q#49454, answer score: 3
Revisions (0)
No revisions yet.