Question

I'm doing the code academy stream and I have a little experience in Ruby. I don't understand why the check_angles(self) function needs the self parameter.

The reason I'm confused is that I don't understand what is passing the self parameter to the function when it is called. it seems like the function call (the last line of the code block) is passing self implicitly, but the function requires self explicitly defined as a parameter.

Why is this?

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):
        sum_angles = self.angle1 + self.angle2 + self.angle3
        if sum_angles == 180:
            return True
        else:
            return False

    tri = Triangle(45,34,78)
    tri.check_angles(EMPTY BUT WHY)
Was it helpful?

Solution

The way this works in Python is that once you instantiate a class Foo with a method bar(self), the function used to create the method is wrapped in an object of type instancemethod which "binds" it to the instance, so that calling foo_inst.bar() actually calls Foo.bar(foo_inst).

class Foo(object):
    def bar(self):
        print "called bar on %s" % self

foo_inst = Foo()

# these 2 calls are equivalent
foo_inst.bar()
Foo.bar(foo_inst)

or, interactively:

>>> Foo.bar
<unbound method Foo.bar>

>>> Foo().bar
<bound method Foo.bar of <__main__.Foo object at 0x10675ecd0>>

so as you can see, while still attached directly to the class, bar is an unbound method and still has the self argument, however, when retrieving the method object from a Foo instance, it has become a bound method whose self parameter is already pre-set to the instance you retrieved the method object from.

This is also the reason why self can really be called anything you want such as arg0 or this or me or putin etc.

In fact, it becomes even more visible that methods are actually functions under the hood in this example:

class Foo(object):
    pass

def bar(arg0):
    print "called bar with %s" % arg0

Foo.bar = bar

Foo().bar()  # prints: called bar with <Foo object at 0x10675b2d0>

See also Python Descriptors @ https://docs.python.org/2/howto/descriptor.html for how this is implemented and how you can implement similar schemes yourself.

OTHER TIPS

When you call tri.check_angles() you are confused because the function check_angles takes one argument. In fact, you're right. The tri is the argument that is passed as self.

self is used in classes to hold variables that are local to a specific instance of the class.

Example

class A():
    def __init__(self):
        self.x = 2

>>> a = A()
>>> b = A()
>>> print a.x
2
>>> print b.x
2
>>> a.x = 5
>>> print a.x
5
>>> print b.x
2

whereas, if you had just x instead of self.x and you changed the value of x for one instance, the value of x for all instances would change.

Hope that helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top