Reputation: 677
I am trying to implement my own class for complex numbers, to better understand how classes work in python. I have been trying to replace the str magic method to print the complex number in the a+bi format.
def __str__(self):
out="%i" % self.real
if self.imaginary==0: return out
if self.imaginary>=0: out+="+%ii" % self.imaginary
else: out+="%ii" % self.imaginary
return out
what I am interested in is the pythonic way of writing this unappealing block of code, if there is any to implement the fact that if imaginary part is negative, i should get a-bi and if imaginary part is 0 i should get a?
Upvotes: 1
Views: 2767
Reputation: 26946
What about just going a bit more explicit:
class Complex(object):
IM_TOKEN = 'i'
def __init__(self, real_part=0, imag_part=0):
self.real = real_part
self.imag = imag_part
def null_imag(self):
return self.imag == 0
def null_real(self):
return self.real == 0
def __str__(self):
if self.null_imag():
return str(self.real)
elif self.null_real():
return str(self.imag) + type(self).IM_TOKEN
else:
return '{}{:+}{}'.format(self.real, self.imag, type(self).IM_TOKEN)
and testing it:
import itertools
for r, i in itertools.product([1, -1, 0], [1, -1, 0]):
print(f'real: {r}, imag: {i}, complex: {Complex(r, i)}')
real: 1, imag: 1, complex: 1+1i
real: 1, imag: -1, complex: 1-1i
real: 1, imag: 0, complex: 1
real: -1, imag: 1, complex: -1+1i
real: -1, imag: -1, complex: -1-1i
real: -1, imag: 0, complex: -1
real: 0, imag: 1, complex: 1i
real: 0, imag: -1, complex: -1i
real: 0, imag: 0, complex: 0
As a side note the ==
does not work well with float
data.
Upvotes: 1
Reputation: 69983
If you are using Python 3.6+, use f-strings as follows:
def __str__(self):
if self.imaginary == 0:
return f'{self.real}'
if self.real == 0:
return f'{self.imaginary}i'
return f'{self.real} {self.imaginary:+}i'
If you are using a version prior to Python 3.6, you should use format.
def __str__(self):
if self.imaginary == 0: return '{}'.format(self.real)
if self.real == 0: return '{}i'.format(self.imaginary)
return '{} {:+}i'.format(self.real, self.imaginary)
I have also improved a bit the logic. Basically, when it has no imaginary part it is just returning the real part, if there is no real part, it is returning the imaginary part. When it has both imaginary and real part, it returns the complex number.
Notice that +
specified after the two dots is the format. This format allows you to have the the sign of the imaginary part printed.
Examples
Assuming that your class is named CNumber
>>> x = CNumber(10, 1)
>>> str(x)
'10 +1i'
>>> x = CNumber(5, 0)
>>> str(x)
'5'
>>> x = CNumber(0, 3)
'3i'
>>> x = CNumber(1, -1)
'1 -1i'
If you want the following format a + bi
def __str__(self):
if self.imaginary == 0: return f'{self.real}'
if self.real == 0: return f'{self.imaginary}i'
sign = '+' if self.imaginary > 0 else '-'
return f'{self.real} {sign} {abs(self.imaginary)}i'
Upvotes: 1