Ex.41 can't get the basics right

I’ve been looking OOP and exercise 41.

I’m trying to wrap my head wrap around classes and object.
I found that website describs a class as
‘A class is a blueprint of an instance of an object’ - - which makes sense to me.

But then a few things confuses me in ‘Learn Code The Hard Way’
But might be me reading it wrong.

This is where I’m stuck:

object Two meanings: the most basic type of thing, and any instance of some thing.
I get the first part about the most basic type. fx ‘man’ is the basic object which is an instance of the class called ‘human’. ‘man’ has a bunch of properties such as name, hair and eye_color and some methods such as running, walking and sitting.
However I don’t get any ‘instance of some thing’?

instance What you get when you tell Python to create a class.
I might have gotten this wrong, but isn’t an object and instance of a class. ‘John’ and ‘Bob’ are two instances of the ‘human’ class?
Or is the human class that an instance?
Or is anything an instance fx. the ‘human’ class is one instance of the ‘mammal’ class. And ‘John’ and ‘Bob’ are then two instances of the the ‘human’ class?

self Inside the functions in a class, self is a variable for the instance/object being accessed.
self and init I really do not understand. To me it seems its variables that for what ever reason is used in classes. But I can’t figure out why they’re so important. Couldn’t they be called anything?

#I found the below which I understand the concept behind 
#but do not understand what self and __init__ does

class Dog:
    def __init__(self, legs, colour):
        self.legs = legs
        self.colour = colour

fido = Dog(4, "brown")
spot = Dog(3, "mostly yellow")

class X(object): def init(self, J) class X has-a init that takes self and J parameters.
Is this the same as class X(Y): def init(self, J) or “make a class named X that is a Y that has a init that takes self and J parameters”?
or is (object) something special or can it be named anything?

Hope someone can shed some light on my confusion.

The class is the template. When you use the template, you create instances of it. The cookie cutter is an example: you make the mould and then use it to create instances of the cookie mould shape.

Now when you create the instance, you might want to initialise it with some stuff. That is all init does. And when you reference your instance, you use ‘self’ so Python knows you are talking about the instance in play at the time, not some other instances you may have.

In the Dog Class example, when an instance is created, it must have arguments for legs and colour. Those are the initialisation arguments that are needed for any instances.

1 Like

Hi @ktrager.

I also had real problems with this one.
I will make an attempt to explain some of what you want help with.

One can create a class with this:

class MyPet:
    pass
# or
class MyPet():
    pass
# or
class MyPet(object):
    pass

I have seen all three of them and they seems to work fine all of them.
Probably there are some occasion when one of them is better than the other.
I know Zed prefer the last example.

You can create a class like this:

class Pet(object):
   
    def name(self):
        return 'Fido'
 
    def age(self):
         return 8
 
my_dog = Pet()
my_cat = Pet()
 
print(my_dog.name())
print(my_dog.age())

print(my_cat.name())
print(my_cat.age())

As you can see this one has no init.
I created methods for name and age and a return value for each
Then I instantiated the class with “my_dog = Pet()” and my_cat = Pet().

Edit:
I guess one can say the instance of Pet() is a variable connected to this class.

But as you can see, all of the instances (my pets) all got the same name and age.

Its now we have use for the init method.

class MyPet(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age


my_dog = MyPet('Fido', 8)
my_cat = MyPet('Brutus', 12)
my_fish = MyPet('Nemo' ,2)

print(my_cat.name)
print(my_cat.age)

In this class I put in a init with (self, name, age)
As you can see when I instantiated the class I also provided name and age in the brackets.
So all pets now can have their own name and age.

And yes, “self” can be replaced by something else.
But I think it is a good idea to follow recommendation to use “self”.
I guess one reason is that some day one will mix a own choosen name with another variable.

I hope this is helpful.

1 Like

Just to be clear, the instance is not a variable associated with the class. It’s an entirely different object. This is important for when you deal with inheritance, or overloading.

1 Like

Hi @gpkesley
Thanks for clarifying.
I edited a little to point out your comment about this.
And learned a lesson. :man_student:
Again. :slight_smile:

Sorry if that sounded short! I meant, variables are containers for data, that can be properties of a class/instance.

Hi @ulfen69 and @gpkesley

This cleared out alot of stuff.

This now kind of make sense.
Is it safe to say that init is a special method inside classes that allow me to assign and ‘empty/open’ variable/container inside a function. And the self makes sure im referencing only the particular container specified by init?

I tried to do the following:

class Mypet(object):

    def __init__(self, name, age):
        self.name = name
        self.age= age+4


    def __init__(self, name2, age2, color2):
        self.name = name2
        self.age = age2
        self.color = color2


mydog = Mypet("Fido", 8, "Brown")
mycat = Mypet("Brutus", 12, "Black")
myfish = Mypet("Nemo", 2, "Red")

print(mydog.name)
print(mycat.age)
print(myfish.color)

The above jumps the first function and goes into 2nd one mainly because it has 3 arguments.
But if I take an argument away then it comes with an error and says I need one more argument.
This leads me to think that I only use init once in a class?

I’m still not sure what the object does in class Mypet(object): especially if it also works without.
But guess this might become clearer the further i go down the rabbit hole?

Python developers like explicitness so as the class is an object, they specify that… Class(object): although as you’ve seen it’s not technically required as necessary syntax.

The init method (called dunder init as it has double underscores) is one of Pythons special methods that is applied at initialisation of an object (hence the init name). But try mentally replacing ‘init’ with ‘build’ and you see you are defining a special method to be run automatically when the instance is built.

And as you say, because you might build lots of instances, self just refers to the built one you have in scope at the time the code is run.

So many of us have taken some time to get our heads around this. Don’t worry, keep hacking and one day it will click. I like your experiments too. Very interesting! Sometimes weird stuff opens new doorways of understanding.

1 Like

Thank you @gpkesley for putting this down in plain writing :pray:.
I’m trying to keep up with programming lingo, I can see how init can be replaced a ‘build’ that automatically builds the instance when created.