What are the differences between instance variables and class variables, or why do I need to use `self.pi`?

Thanks @mtf. your explanations are extremely helpful!

3 Likes

You raise an interesting questions

class Circle:
  pi = 3.14
  radius = 0
  def __init__(self, diameter):
    print("Creating circle with diameter {d}".format(d=diameter))
    # Add assignment for self.radius here:
    Circle.radius = diameter / 2  #<-----------------------
    
  def circumference(self):
    return Circle.radius * Circle.pi * 2  #<-----------------------

when you use name of class => Circle instead on name of instance when you create object from Class you are changing Class variable based on your last instance creation of class and value of radius will depend on value of your last instance you created .
let say you created instance with and pass arguments to init method as 12 now Circle.radius has value of 6 and since every instance have access to all variables of mother class it inherit varibales of Class . what you do by doing Cricle.radius = ā€œvalueā€ is saying == > I change object factory (which is class) 's radius variable every time I create instance of it .

you could take a look at an expm :

class Circle:
  pi = 3.14
  radius = 0
  def __init__(self, diameter):
    print("Creating circle with diameter {d}".format(d=diameter))
    # Add assignment for self.radius here:
    Circle.radius = diameter / 2  #<-----------------------
    
  def circumference(self):
    return Circle.radius * Circle.pi * 2  

  
circle_one = Circle(12) # here I changed Class variable Circle to be value of 6
print(circle_one.radius) # since instance of Class inherit all variables form Class this will print 6

circle_two = Circle(16)  # now I change class variable radius to be 8
print(circle_two.radius) # this will print 8
print(circle_one.radius) # this will also will print 8 , (return the value was 6 before creation of last instance 

can we create object without creating Class ? like what we do in JS ? In JS the reason behind idea of classes was create a blueprint to save us time from re-creating common methods and variables for certain entity like animals(as class) and cat or dog 's are objects inherit all methods and variables of animals(class).
I did search google and could not find an answer.

In Python, everything is an object. Only thing is they can only inherit from their parent class.

str

cannot inherit from,

list

which cannot inherit from,

dict

and so on. Itā€™s up to us to extend the parent class to give our custom objects additional methods that it might need for our purposes.

Just as we can define a literal in JS,

obj = {
    key: 'value'
}

we can define a literal in Python,

obj = {
    'key': 'value'
}

which will create an instance of the dict class.

could we say classes in python are more extended then classes in JS ?
And class definition and class instance(object) in JS is only part of what python offers us which is dict class and dict object ?
And class definition in whole JS is like a small part of what classes are in python and it is Dict class and dict object.

and thatā€™s why we could bypass creating of class and directly create class instance in Js which is instance of object class and if yes how we could create instance of class before creating class ā€¦ in JS

sorry for asking this questions .

When it comes down to it there is nothing special about classes other than that they define a type of object.

>>> type({})
<class 'dict'>
>>> isinstance({}, dict)
True
>>> 

We can even make a class from a classā€¦

>>> class Array(list):
    def __repr__(self):
        return str(type(self))
    def get(self, x):
        return self[x]         #  error prone

	
>>> arr = Array()
>>> print (arr)
<class '__main__.Array'>
>>> isinstance(arr, list)
True
>>> arr.extend([1,2,3,4,5])    #  Recognize this list method?
>>> arr.get(2)
3
>>> 

Or with a slight twistā€¦

>>> class Array(list):
    def __repr__(self):
        return str(type(self))
    def get(self):
        return [*self]         #  less error prone

	
>>> arr = Array()
>>> print (arr)
<class '__main__.Array'>
>>> isinstance(arr, list)
True
>>> arr.get()
[]
>>> arr.extend([1,2,3,4,5])
>>> arr.get()
[1, 2, 3, 4, 5]
>>> 

Really no magic. Our class is an extension of the List class.

>>> other = Array()
>>> other.extend([6,7,8,9,10])
>>> arr.get()
[1, 2, 3, 4, 5]
>>> other.get()
[6, 7, 8, 9, 10]
>>> other.get()[2:]
[8, 9, 10]
>>> 

Whatā€™s neat here is that our object is not subscriptable. It can only be polled with its .get() method, which returns a normal list.

However, as weā€™ve already seen, we can still use list methods on the object.

>>> other.remove(8)
>>> other.get()
[6, 7, 9, 10]
>>> other.insert(2, 8)
>>> other.get()
[6, 7, 8, 9, 10]
>>> arr.extend(other.get())
>>> arr.get()
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> 
1 Like

The two languages are in a completely different environment even while it looks as though they do things the same way. Truth is, they donā€™t.

All we can compare is constructs and algorithms. We can emulate between languages by getting one language to do the same thing with the same inputs as the other. The best we can then determine is which language made it easier because of intuitive underpinning and/or human readability.

1 Like

2 posts were split to a new topic: Circle.radius ie a class variable

I notice we can define pi as an instance variable, and the code works

class Circle:
  
  def __init__(self, diameter):
    print("Creating circle with diameter {d}".format(d=diameter))
    # Add assignment for self.radius here:
    
    self.radius = diameter / 2
    self.pi = 3.14
  def circumference(self):
    return 2 * self.pi * self.radius

What are the benefits to have pi as a class attibute (not sure how to call it)?
or we will learn why when the code gets more complicated like using two or three classes in one go?

Thanks

A class attribute is shared by all instances. Meaning if pi changes, it does for all instances, not just one.

you make a good point here, as code complex you want to do things the right way, otherwise maintaining and reading the code becomes very difficult.

2 or 3 classes is still very little. I have projects where i use dozen if not hundred of classes. Then you certainly want to use the right type of attribute :wink:

3 Likes

thank you so much! :slight_smile:

1 Like

Please donā€™t use too many jargons. It is very difficult to understand the explanation. Use more plain terms.

1 Like

Please describe for us what you see as ā€˜jargonsā€™. How might one put them in plain terms?

thank you for sharing this video, it helped me alot

Thank you MTF!

You just helped me to completely understand instance variables, class variables and why we use selfā€¦that example just gave me an ā€œA-haa!ā€ moment. Much appreciated. :pray:

3 Likes

Yes unfortunately anything i dont understand on this paid course is gone through Corey Schaefers youtube tutorials for free. FRUSTRATING.

Yeah, Iā€™m struggling with classes, Iā€™m not even sure what the purpose of it is. Guess i have to look elsewhere for this and come back here to revise.

In the simplest way, classes are a way to organize/structure our code. But this really only start paying off once your code-base starts to grow.

and this is where the paradox occurs, you will need to learn the basics of classes first before you can apply it in a larger code-base. Which is why initially (when learning about classes), they seem more confusing and only add a lot of boilerplate code

codecademy mostly focuses on teaching on how question, and not the why question

3 Likes

Makes a lot of senseā€¦ Thank you for putting it into context.

1 Like

Iā€™ve been doing a lot of research on classes these past couple days, and from what I gather is that they are just an ā€œorganizational toolā€. I include quotes because ā€œorganizationalā€ is subjective, and many full time programmers consider OOP to be ridiculous. Whether that is the case or not, I am too inexperienced to form an actual statement.

2 Likes