0

I'm trying to make a class of Polar numbers without using libraries that make all the work for me. I was trying to make the pow function. Polar numbers when are raised to a power between 0 and 1 you expect multiple results, and the thing is that my code is behaving like a generator and I think it shouldn't.

import math

def sin(x,/):
    return math.sin(math.radians(x))

def cos(x,/):
    return math.cos(math.radians(x))

def arctan(x,/):
    return math.degrees(math.atan(x))


class polar():
    def __init__(self, complex_num,angle=None):
        if angle != None:
            self.r = complex_num
            self.alpha = angle
        elif type(complex_num) in (float, int, complex):
            complex_num = complex(complex_num)
            self.r = ((complex_num.real**2)+(complex_num.imag**2))**0.5
            if complex_num.real != 0:
                if complex_num.imag > 0 and complex_num.real > 0:
                    self.alpha = arctan(complex_num.imag/complex_num.real)
                elif complex_num.imag > 0 and complex_num.real < 0:
                    self.alpha = 180-(arctan(complex_num.imag/abs(complex_num.real)))
                elif complex_num.imag < 0 and complex_num.real < 0:
                    self.alpha = 180+(arctan(abs(complex_num.imag)/abs(complex_num.real)))
                else:
                    self.alpha = 360-(arctan(abs(complex_num.imag)/complex_num.real))
            else:
                if complex_num.real > 0:
                    self.alpha = 90
                else:
                    self.alpha = 270
        while self.alpha >= 360:
            self.alpha -=360
        while self.alpha < 0:
            self.alpha += 360
            

    def __pow__(self,exponent):
        result = []
        if type(exponent) not in (int,float):
            raise TypeError("Exponent must be a number")
        if exponent == 0:
            return polar(1,0)
        elif exponent == 1:
            return self
        elif exponent > 1 or exponent < 0:
            return polar(self.r**exponent, self.alpha*exponent)
        else:
            index = int(1/exponent)
            for i in range(index):
                alpha = (self.alpha/index) + ((360/index)*i)
                result.append(polar(self.r**exponent, alpha))
            return result
                
            
            
    def __str__(self) -> str:
        return f"{self.r} {self.alpha}º"
    
    def complexToPolar(polar_num: str,/):
        try:
            polar_num = polar_num.replace("º","")
            polar_num = polar_num.split()
            r = float(polar_num[0])
            alpha = float(polar_num[1])
            z = r*(cos(alpha)+sin(alpha)*1j)
            return z
        except:
            raise Exception(TypeError)

print(polar(0-243j)**(1/5)

I tryed to use yield but the variable "i" wasn't incrementing at all, so I could get the fist result but not them all, the expected result is: [3.0 54.0º, 3.0 126.0º, 3.0 198.0º, 3.0 270.0º, 3.0 342.0º] But what i'm getting is: [<__main__.polar object at 0x00000198710D66D0>, <__main__.polar object at 0x00000198710D6690>, <__main__.polar object at 0x00000198710D68D0>, <__main__.polar object at 0x00000198710D65D0>, <__main__.polar object at 0x00000198710D6850>]

BerniusIII
  • 13
  • 4
  • `yield` won't work unless the caller iterates over it, e.g. `for res in polar(0-243j)**(1/5):` – Barmar Apr 05 '23 at 22:53
  • Maybe you want to define `__repr__` with `__str__`? – metatoaster Apr 05 '23 at 22:54
  • `__pow__` is inconsistent in what it returns. Sometimes it returns a `polar` object, but in the `else:` block it returns a list. This isn't going to work because the list won't participate in chained arithmetic operations. – Barmar Apr 05 '23 at 22:55

1 Answers1

0

You made a list of polar objects inside __pow__ and then you returned it. That's exactly what you see with [<__main__.polar object at ...

So the only thing that is wrong is your print statement at the end. This works:

for obj in polar(0-243j)**(1/5):
    print(f"{obj.r} {obj.alpha}º")

Output:

3.0 54.0º
3.0 126.0º
3.0 198.0º
3.0 270.0º
3.0 342.0º

If the for _ in thing is hard to see, then play with it one statement at a time on the console:

>>> mylist = polar(0-243j)**(1/5)
>>> mylist
[<__main__.polar obje...86F8DE8C0>, <__main__.polar obje...86F8DEA10>, <__main__.polar obje...86F8DE9B0>, <__main__.polar obje...86F8DE950>, <__main__.polar obje...86F8DE8F0>]
>>> mylist[0]
<__main__.polar object at 0x000001A86F8DE8C0>
>>> mylist[0].r
3.0
>>> mylist[0].alpha
54.0

Edit: Ok, my eyes skipped over your __str__ definition. @metatoaster's comment is correct. Just replace it with __repr__ and you're good.

picobit
  • 527
  • 5
  • 15