Instantiate an Object help


#1

I can't understand how I need to format some things in this program. It gives me an error all the time. Here is my code.

class Triangle(object):
    number_of_sides = 3
    def __init__(self,angle1,angle2,angle3):
        angle1 = self.angle1
        angle2 = self.angle2
        angle3 = self.angle3
    def check_angles(angle1,angle2,angle3):
        if self.angle1 + self.angle2 + self.angle3 == 180:
            return True
        else:
            return False
my_triangle = Triangle(90,30,60)
print my_triangle.number_of_sides
print my_triangle.check_angles()

#2

The error message in question would be relevant, but sure, I'll run it.

Traceback (most recent call last):
  File "herpaderp.py", line 12, in <module>
    my_triangle = Triangle(90,30,60)
  File "herpaderp.py", line 4, in __init__
    angle1 = self.angle1
AttributeError: 'Triangle' object has no attribute 'angle1'

Well, ok, have you read the error? Which value are you assigning to which variable?


#3

the value of 90 should be assigned to the angle1, but the error says there is no such thing as angle1, but I have it assigned in the init method.


#4

Not necessarily 90, but anything specified by the parameter for that argument. Which one is that? And what do you assign to? Where do you assign from?

If you stop and think for a while, ignore the method, where should it be stored?


#5

I don't understand methods very well so I don't know how to answer you. I think the first value stated in

my_triangle = Triangle(90,30,60)

should be stored in self.angle1 because thats what I assigned it as in the init method. I don't know what else I need to do or change.


#6

Correct.

You are not doing that in your code. Look at your assignments.


#7

should be self.angle1=angle1 and so on

And this "print my_triangle.check_angles()" needs arguments.

hope It is useful


#8

I changed the

angle1 = self.angle1

to the other way around

self.angle1 = angle1

and I stopped getting the error:

Traceback (most recent call last):
  File "<stdin>", line 15, in <module>
  File "<stdin>", line 5, in __init__
AttributeError: 'Triangle' object has no attribute 'angle1'

However I can't figure out how to give

my_triangle.check_angles()

the arguments it needs. I tried doing

print my_triangle.check_angles(angle1,angle2,angle3)

and

print my_triangle.check_angles(my_triangle.angle1,my_triangle.angle2,my_triangle.angle3)

and

print my_triangle.check_angles(90,30,60)

but they return errors that don't make sense to me every time. Like this one:

Traceback (most recent call last):
  File "<stdin>", line 16, in <module>
TypeError: check_angles() takes exactly 3 arguments (4 given)

I mean obviously I only input 3 arguments especially in the last one. I don't understand where it is getting 4 from.


#9

That method doesn't need any arguments, because that data is stored in the object.


#10

Ok I think what you said kind of broke through and made some things make more sense to me, I changed my code again so the

def check_angles():

takes no arguments, and when the method is executed later it doesn't have arguments in it, but I still get this error.

Traceback (most recent call last):
  File "<stdin>", line 16, in <module>
TypeError: check_angles() takes no arguments (1 given)

just to make sure we're on the same page, here is my program at this point.

class Triangle(object):
    number_of_sides = 3
    def __init__(self,angle1,angle2,angle3):
        self.angle1 = angle1
        self.angle2 = angle2
        self.angle3 = angle3
    def check_angles():
        if self.angle1 + self.angle2 + self.angle3 == 180:
            return True
        else:
            return False
my_triangle = Triangle(90,30,60)
print my_triangle.number_of_sides
print my_triangle.check_angles()

So why is it telling me that I have given it one more argument than it requires when I haven't given it any at all?


#11

Dun Dun Dun Dah!!!
I figured it out. I did some googling and found out all methods require self as part of their arguments. I thought it was only the init one. Phew. Thanks for the help ionatan and python_of_pythons


#12

Yeah, I can add a few more pieces to the puzzle to explain somewhat why self is used the way it is

if you have an object, say, x and you request a method: x.some_method
then a whole bunch of things have happened in the background, even though you haven't even called the method yet.

The value that you receive by doing that, x.some_method is a bound method which is an association between an object and a method.

Which means, that you can store it away for later use, and it will still be bound to the object that you got it from.

a = []
b = a.append
b(5)
b(300)
print a # [5, 300]

So that bound method, when called, will call the method-code with the object as the first argument, followed by the arguments to the bound method.


#13

Ok I think that makes sense.

Also I found this in a subsequent lesson, I don't know why it wasn't before the lesson I was struggling with. They seem to be out of order or something.

"Just like when we defined init(), you need to provide self as the first argument of any class method."


#14

That's some clumsy wording in the instructions, because:
a function has parameters, and receives arguments.

https://docs.python.org/3.3/glossary.html#term-argument
https://docs.python.org/3.3/glossary.html#term-parameter


#15

Oh and you can also create methods that do not require an object! Fancy syntax:

class HerpDerp(object):
    @staticmethod
    def add_5(x):
        return x + 5

print HerpDerp().add_5(3) # 8

Maybe I shouldn't feed you with so much confusing stuff haha. Don't worry if you're not keeping up. I am soo off-road right now.

What the @ with a name after does is it replaces the function (here it's add_5) that it's put on, and returns another function that does some extra stuff and and then calls the replaced function. So for staticmethod, it'll discard the self argument

The above is equivalent to:

class HerpDerp(object):
    def add_5(x):
        return x + 5
    add_5 = staticmethod(add_5)

print HerpDerp().add_5(3) # 8

So the argument to staticmethod is a function. functions are values, we did the same thing with list.append in my previous post. staticmethod then creates a completely new function that usesadd_5` and returns this new function


#16

By now I'm just entertaining myself by writing this out..

A simplified version of staticmethod could look like:

def my_staticmethod(m):
    def wrapper(self, *args):
        return m(*args)
    return wrapper

So it creates a function, wrapper that takes self and then any amount of arguments. All it does is to call m with all arguments except the first.
That wrapper function is then returned so that the caller can replace the original with the wrapper.

Let's try it!

class Derp(object):
    @my_staticmethod
    def add_8(x):
        return x + 8

Derp().add_8(5) # 13

The real one is likely much more fancy with a bunch of sanity-checking and making the wrapper look like the original function. It's also a class, not a function (an object can be called if the class has a __call__ method!


#17

you placed the variable the number_of_sides = 3 on wrong place
you have to define inside class :slight_smile:

class Triangle(object):
def init(self,angle1,angle2,angle3):
self.angle1=angle1
self.angle2=angle2
self.angle3=angle3
number_of_sides=3

def check_angles(self):
    if self.angle1+self.angle2+self.angle3==180:
        return True
    else:
        return False

my_triangle = Triangle(90,60,30)
print my_triangle.number_of_sides
print my_triangle.check_angles()


#18

Can someone also help me because my code shows this error: Oops, try again. Did you create an instance of Triangle called my_triangle?

Below is my code:

class Triangle(object):
number_of_sides = 3
def init(self, angle1, angle2, angle3):
self.angle1 = angle1
self.angle2 = angle2
self.angle3 = angle3

    def check_angles(self):
    if self.angle1  + self.angle2 + self.angle3 == 180:
        return True
    else:
        return False