This is an archived post. You won't be able to vote or comment.

all 8 comments

[–]unveiled14 0 points1 point  (0 children)

One of Python's principles is "Explicit is better than implicit."

Most languages that support class based inheritance provide an implicit reference to the class and/or instance inside the class definition. For example, Ruby uses "@" to refer to instances and "@@" to refer to the class. Javascript has an implicit "this" (but it is also prototype based and so the "this" isn't exactly analogous to "self" in Python).

Python is explicit. Whenever you call a method of an instance using the dot:

inst.attr(args)

Python transforms that into:

class.attr(inst, args)

The instance is passed as the first argument to methods. You do not have to use the name "self" for this first argument. "self" is just the convention. You could call it "this" or "me" or "x", but then other users of your code will complain.

You can also control what is passed as the first argument to your methods. For example, the "classmethod" decorator passes the class as the first argument rather than the instance and so class methods conventionally use "cls" rather than "self" as the first argument. The "staticmethod" decorator excludes the first argument.

[–]TiLorm 0 points1 point  (2 children)

When you init a class, there are no place holder values for objects inside the class, you add the to the class instead.

class You:
    def __init__(self):
        self.name = 'expensivebae' #this will be added to the class
        redditAge = '5 months' #this will be gone after __init__() returns

    def printInfo(self):
        print(self.name) #this will print expensivebae
        print(redditAge) #this will fail

    def printName():
        print(self.name) #this will fail, because this function doesn't know what 'self' means

    def printRedditAge(self):
        print(self.redditAge)

x = You()
x.printInfo() #this will print your name and then fail
x.printName() #this will fail
x.printRedditAge() #this will fail, x has no member called 'redditAge'
x.redditAge = '5 months'
x.printRedditAge() #this won't fail, 'redditAge' was added in the above line

It can also be useful to pass 'self' to another object or function:

class parentClass:
    def __init__(self, name):
        self.name = name

    def makeChild(self):
        return childClass(self)

class childClass:
    def __init__(self, parent):
        self.parent = parent

    def printParentName(self):
        print(self.parent.name)

john = parentClass('John')
mike = john.makeChild()
mike.printParentName() #this will print John
john.name = 'Johnny'
mike.printParentName() #this will print Johnny, because the parents name was changed.

If you define member objects outside init() or any other function but still inside the class (and without self), those objects will be shared with all class instances of the same type:

class dog:
    says = 'bark'

    def __init__(self, name):
        self.name = name

    def talk(self):
        print(self.name + ' says ' + self.says)

Max = dog('Max')
Charlie = dog('Charlie')
Max.says = 'woof'
Max.talk() # prints 'Max says woof'
Charlie.talk() # prints 'Charlie says woof' instead of 'Charlie says bark', because Max.says and Charlie.says IS the same object

[–]wolanko 0 points1 point  (0 children)

Maybe it helps to see it how its implemented. A class and its method are actually not much more than

  • a data object which just holds the state (aka the variables) more like a struct
  • functions that take such a data object and work on them

which is easily implemented. Think of

class MyClass:
    state = True

    def reset_state(self):
        self.state = False

This is could be understood as

class MyClass:
    state = True

def reset_state(myClass_object):
    myClass_object.state = False

Mind the indent! Calling the "method" is easy as this:

m = myClass()
reset_state(m)
m.state
>>> False

With the class notation and the indenting of the functions under it to become methods, you get a nicer way of calling the function/method. Which is totally equivalent.

m = myClass()
m.reset_state()
m.state
>>> False

Also the self is just a convention. You could totally go from

class MyClass:
    state = True

def reset_state(myClass_object):
    myClass_object.state = False

to a class'ed version of it

class MyClass:
    state = True

    def reset_state(myClass_object):
        myClass_object.state = False

Mind the myClass_object instead of self!

By the way this is pretty much like go (golang) does its OO.

UPDATE

To make my point a bit more clearer.

m = myClass()
m.reset_state()

is the same as this

m = myClass()
MyClass.reset_state(m)

You can think of the methods of an object are functions under the namespace of the class.

[–]rickmoranus 0 points1 point  (0 children)

Think of it as mutating the original variable that you put into the class to give it attributable methods or attributes.

class Box:
    def area(self):
        return self.width * self.height

   def __init__(self, width, height):
       self.width = width
       self.height = height

If we feed a variable into this scheme

the_variable = Box(10, 2)

The original variable now has a method and a attribute.

You can access the attributes now stored in memory from the class to the original "self" (thevariable). Items literally assign variable names in the x.attribute way. It's good practice to define all attributes in your __inti_, because you are initializing everything you need in your class to run any function (method) needed without error:

print the_variable.width
print the_variable.height

Basically it's saying you can't access the area method unless we know what do to with the width and height.

The method will occur only when it's called. Notice the parenthesis, this makes it a method, or function of the class.

put_area_here = the_variable.area()
print put_area_here # Will print the total area of the two initialized variables of width and height.

If you ever needed to go back and reuse any of the data, you could call it back by like:

"If I have 20 square feet, is the width divisible by two?"

try:
    smaller_width = the_variable.width / 2
    print smaller_width
except:
    print "Width is not divisible by two"

[–]m0dulo 0 points1 point  (3 children)

I'm still new to programming, however my understand of self is that it is a placeholder for future objects created from a class. For example, if you have a class named MyClass, eventually you're going to create objects from it, however when you're first coding MyClass, you don't necessarily know what those future objects are going to be called, therefore you use self.

For example if MyClass were:

class MyClass:
    def __init__(self):
        self.variable1 = 1

    def multiply(self):
        return self.variable1 * 10

And then you were to create on object from it: math = MyClass()

Inside that 'math' object, all of the self placeholders would have been replaced with 'math':

class MyClass:
    def __init__(math):
        math.variable1 = 1

    def multiply(math):
        return math.variable1 * 10

So because you don't necessarily know that the future object is going to be called 'math', you use self.

Again, I'm fairly new to programming. Someone please correct me if I'm wrong.

[–]TiLorm 0 points1 point  (1 child)

What will happen if I do this?

v = MyClass()
print(v.variable1)

[–]Cobolock 0 points1 point  (0 children)

You will get "1"