The following function raises meaningful exceptions if its argument is not a list or tuple of two or three items, each of which can be meaningfully be represented as a real number.
def str_vector(v):
if type(v) is not list and type(v) is not tuple:
raise TypeError('argument to str_vector() must be a list or tuple')
if len(v) not in (2,3):
raise ValueError('vector must be 2D or 3D in str_vector()')
unit_vectors = ['i','j','k']
s = []
for i, component in enumerate(v):
try:
s.append('{:s}{:1s}'.format(str(float(component)), unit_vectors[i]))
except (TypeError, ValueError):
raise ValueError('Invalid element in vector {}: {} is'
' not a real number'.format(v, component))
return ' + '.join(s).replace('+ -', '- ')
After checking that the argument is of the correct type and length, its items are converted to float
; the possible TypeError
and ValueError
exceptions are handled and a new ValueError
exception is raised if the conversion fails.
A couple of other things to note: we let Python's own str
builtin convert the float
back into a string for the output of each component rather than work out how to format it ourselves; secondly, the string components are concatenated with ' + '
but then modified for negative components so that, for example, ' + -2'
is rendered ' - 2'
.
>>> str_vector((4, 0.5, -2)) # OK - all real numbers
4.0i + 0.5j - 2.0k
>>> str_vector((-2, '3.5')) # also OK
-2.0i + 3.5j
>>> str_vector('oops')
...
TypeError: argument to str_vector() must be a list or tuple
>>> str_vector([2,1,2,3])
...
ValueError: vector must be 2D or 3D in str_vector()
>>> str_vector((1, 0, 4j))
...
ValueError: Invalid element in vector (1, 0, 4j): 4j is not a real number