0

The following code is the initialization method of a basic Angle object with float as its parent class.

class Angle(float):
    def __init__(self, value, vertex2 = None, vertex3 = None, atype = 'convex'):

        #type-checking for the input args
        try:
            #checks for value arg
            angle = value
            if not (0 < value < 360):
                angle %= 360
        except TypeError:
            #checks for three-vertice args
            try:
                angle = three_point_angle(value, vertex2, vertex3)
                #three_point_angle is a function to calculate the
                #convex angle between three vertices (i.e. at vertex2)
                if atype == 'concave':
                    angle = 360 - angle
                self._vdict = {}
                for pos, vert in enumerate([value, vertex2, vertex3]):
                    self._vdict[pos] = vert
            except:
                raise TypeError(\
                    "You may only specify either an angle value, or three vertices from which \
                    to calculate the angle. You input a %s, %s and %s value." % (\
                        type(value), type(vertex2), type(vertex3)))
        self.angle = angle

The idea behind this class is that you can either input a value for the angle, or specify three vertices (and an optional angle type parameter) to automatically calculate the angle. In the end, self.angle is always initialized, and this is where all the arithmetic takes place (so __add__(self, other) would affect self.angle).

The reason it inherits from float is to inherit its magic methods for reflective and augmented assignment, which are all performed on self.angle.

The problem arises when one tries to input three values for the vertices. Since it inherits from float, it can't take more than one argument, and as such raises an error. How would I work around this? My guess is that I would have to create a __new__ method for Angle, such that it would be invoked instead of the superclass', but I have no clue where I'd even start with that or even if it's the right/best way to go about this.

glglgl
  • 89,107
  • 13
  • 149
  • 217
user3002473
  • 4,835
  • 8
  • 35
  • 61

2 Answers2

1

See this related question:

How to overload `float()` for a custom class in Python?

then change

class Angle(float):

to

class Angle(object):
Community
  • 1
  • 1
Clarus
  • 2,259
  • 16
  • 27
1

You don't need to inherit from float. You're incorrect in thinking that magic methods are performed on self.angle; they're just performed on self. Try the following code:

class Angle(float):
    def __init__(self, x):
         self.angle = x
    def double(self):
         self.angle *= 2
a = Angle(1)
a.double()
print a # prints 1.0
print a.angle # prints 2
a *= 5
print a # prints 5.0
print a.angle # throws AttributeError

a.angle isn't affected by magic methods, nor is float(a) affected by operations on a.angle. floats are immutable, so a *= 5 created a new float, with different attributes.

So, if you change Angle to inherit from Object instead of float, you can control initialization, without losing any convenience.

Chris Barker
  • 2,279
  • 14
  • 15