crazycrazy
crazycrazy

Reputation: 15

How to allow an object to have a class method as an attribute?

Solution at the bottom

Here is my code:

class Points:
    def __init__(self, a, b):
        self.a = a
        self.b = b 

    def gradient(self, coord):
        return (coord[0] - self.a) / (coord[1] - self.b)

class Attribute:
    def __init__(self, coordinate, c):
        self.coordinate = coordinate
        self.c = c

    def isEqual(self, coordinate2, c2):
        print self.coordinate.gradient(coordinate2)
        print self.c == c2

attributes = Attribute([2.345, 2.543], 1.123)
point = Points(3.45, 3.54)
attributes.isEqual(point, 5.0)

So I have a 'Points' class, where I store a coordinate, (a, b), and define a method 'gradient', which takes a list as an argument (another coordinate), and which computes the gradient of a line connecting (a, b) and the new coordinate.

I also have an 'Attribute' class. In this class I define another coordinate as an argument, as well as some other number. This class has a method to check whether the coordinate initiated in this class has the same coordinate as some other coordinate given in the argument of isEqual.

So here I am defining 'attributes' using the class 'Attribute'. I am then calling attributes.isEqual(point, 5.0) to find the gradient between attributes and point and to see if the other number in attributes is equal to 5.

This gives me the following output:

MacBook-Air:Assignment1 Olly$ python try.py 
Traceback (most recent call last):
  File "try.py", line 39, in <module>
    attributes.isEqual(point, 5.0)
  File "try.py", line 33, in isEqual
    print self.coordinate.gradient(coordinate2)
AttributeError: 'list' object has no attribute 'gradient'

I'm not entirely sure how to solve this area. I thought that perhaps I need to inherit the Points class when creating the Attribute class, in order to use the gradient method from the Points class. So I tried changing the Attribute class to the following:

class Attribute(Points):
    def __init__(self, coordinate, c, x, y):
        Points.__init__(self, x, y)
        self.coordinate = coordinate
        self.c = c

    def __str__(self):
        return "a and b (%s, %s); other number %s" % (self.coordinate[0], self.coordinate[1], self.c)

    def isEqual(self, coordinate2, c2):
        print self.coordinate.gradient(coordinate2)
        print self.c == c2

But this gives me a different error:

MacBook-Air:Assignment1 Olly$ python try.py 
Traceback (most recent call last):
  File "try.py", line 37, in <module>
    attributes = Attribute([2.345, 2.543], 1.123)
TypeError: __init__() takes exactly 5 arguments (3 given)

I really don't understand this error.

So could you please help with the following:

  1. Identifying where I am going wrong in the initial case. If I am right and I need to use inheritance, then see 2.
  2. Identifying where I am going wrong in my understanding of inheritance.

Thank you.

Solution (accepted answer from Sweeper)

  1. The code above is confusing Points class with list. They are not the same and cannot be implicitly converted between. The gradient method should take another Point instead of a list:

    def gradient(self, coord):
        return (coord.a - self.a) / (coord.b - self.b)
    
  2. Attribute is being initialised in the wrong way. __init__ takes a Point and a number, but the code above is giving it a list and a number. The following is correct:

    attributes = Attribute(Point(2.345, 2.543), 1.123)
    

Upvotes: 0

Views: 61

Answers (2)

Sweeper
Sweeper

Reputation: 270850

You are confusing your Point class with list. They are not the same at all and you can't implicitly convert between them.

The first thing you should fix is the gradient method. It shouldn't take a list. It should take another Point instead:

def gradient(self, coord):
    return (coord.a - self.a) / (coord.b - self.b)

Secondly, you are initialising your Attribute in the wrong way. The __init__ takes a coordinate and a number, but you are giving it a list and a number.

Create a Point first then create the Attribute:

attributes = Attribute(Points(2.345, 2.543), 1.123)

I don't see why inheritance is appropriate here.

Upvotes: 2

hyperneutrino
hyperneutrino

Reputation: 5425

In your original code at the top, self.coordinate is the list passed into the Attribute constructor. I think you want to be doing coordinate2.gradient(self.coordinate) because coordinate2 is the Point passed in as the argument and self.coordinate is an indexable object, which makes sense for the argument to Point::gradient.

Upvotes: -1

Related Questions