DEV Community

Indrasen
Indrasen

Posted on

Python OOPS basic

In real world everything is Object and every object have 2 things behaviour and attribute. Attribute contains data stored in variable and behaviour is defined as method which is nothing but functions(what's needs to be done)

Imagine there is some kind of phone company manufacturing phone but designed once but created multiple handset. Here design or blueprint is a class and object is a real stuff or entity or instance of class.

class Computer:
    def config(self):
        print("i5, 15gb, 1Tb")

comp1=Computer()
Computer.config()


Output:
D:\Testing Document Sample>C:/Python312/python.exe "d:/Testing Document Sample/calc.py"
Traceback (most recent call last):
  File "d:\Testing Document Sample\calc.py", line 7, in <module>
    Computer.config()
TypeError: Computer.config() missing 1 required positional argument: 'self'
Enter fullscreen mode Exit fullscreen mode

one class have multiple object. this config method will change it's behaviour based on it's object, because different object has different behaviour. If I am calling config, for which object I am calling, like if I say "hey walk" for which object I am calling.
So I have to mention "Hey! Ravi walk" , "Hey! Mukesh walk"
In the same way when I am calling the Computer.config we must say for which object we are talking about, and I am talking about comp1, which means " Hey! I want the config for comp1"
thus writing the update code and run

class Computer:
    def config(self):
        print("i5, 15gb, 1Tb")

comp1=Computer()
Computer.config(comp1)


Output:
D:\Testing Document Sample>C:/Python312/python.exe "d:/Testing Document Sample/calc.py"
i5, 15gb, 1Tb

Enter fullscreen mode Exit fullscreen mode

Here we are calling Computer.config(comp1) where comp1 is passed as arguement to the parameter self under config method. So from there self came up, self is the paramter to pass the object.

If I want to call config for comp2 then. If I run this code we get the same output twice, as we are not changing data as per different object.

class Computer:
    def config(self):
        print("i5, 15gb, 1Tb")

comp1=Computer()
comp2=Computer()
Computer.config(comp1)
Computer.config(comp2)


Output:
D:\Testing Document Sample>C:/Python312/python.exe "d:/Testing Document Sample/calc.py"
i5, 15gb, 1Tb
i5, 15gb, 1Tb
Enter fullscreen mode Exit fullscreen mode

Another to call the method, the first 2 is for Computer.config(comp1) and 2nd two is for comp1.config()

class Computer:
    def config(self):
        print("i5, 15gb, 1Tb")

comp1=Computer()
comp2=Computer()
Computer.config(comp1)
Computer.config(comp2)
comp1.config()
comp2.config()

Output:
D:\Testing Document Sample>C:/Python312/python.exe "d:/Testing Document Sample/calc.py"
i5, 15gb, 1Tb
i5, 15gb, 1Tb
i5, 15gb, 1Tb
i5, 15gb, 1Tb
Enter fullscreen mode Exit fullscreen mode

Now for behind this what's happening. when we use these, as already object is reference with class at time of creation. So behind this scene, config will take comp1/comp2 as arguement and pass to parameter as self. thus most of the code we see this below type of syntax not the old one.

comp1.config()
comp2.config()

ctrl+click bit_length for below example. calling bit_length it will not passing it. so this 'a' is an object it act as arguement and pass it as parameter to self.

eg:
a=3
a.bit_length()

So this is the way that we can create object

Let move further, suppose I want to create different cpu and ram configuration, which require 2 variables, which is cpu and ram. so how to find that.
That's where the picture came special method and variable having underscores (method/variable)

below example as we call config twice the output under init shows twice because we have created 2 objects, which automatically calls the init

class Computer:
    def __init__(self):         //  act as contructor which get called when object created.
        print("initalize init")  
    def config(self):
        print("i5, 15gb, 1Tb")

comp1=Computer()
comp2=Computer()

comp1.config()
comp2.config()


Output:
D:\Testing Document Sample>C:/Python312/python.exe "d:/Testing Document Sample/calc.py"
initalize init
initalize init
i5, 15gb, 1Tb
i5, 15gb, 1Tb
Enter fullscreen mode Exit fullscreen mode

Now Supppose I want to get values based on cpu and ram with respect to object comp1/comp2 so we need to pass the argument mentioning cpu and ram and create variable in init method.
Now since I want cpu and ram values are need to be part of object thus so here is the code for below.

class Computer:
    def __init__(self,cpu,ram):    // self represent object name thus having 3 parameter (self=comp1,cpu='i5',ram=16)
        self.cpu = cpu                // as we need to assign value to object thus using self.cpu=cpu as self is object 
        self.ram = ram
    def config(self):
        print("config is", self.cpu, self.ram)      // Since this CPU and ram is belongs to object thus using self.cpu/self.ram

comp1=Computer('i5',16)
comp2=Computer('Ryzen 3',8)    // passing two arguments to __init__ method

comp1.config()
comp2.config()


Output:
D:\Testing Document Sample>C:/Python312/python.exe "d:/Testing Document Sample/calc.py"
config is i5 16
config is Ryzen 3 8
Enter fullscreen mode Exit fullscreen mode

Thus for the above the data and methods work together i.e binding data with every method so one object has it's own method and has it's own variable.

Comp1 is object or referring to an cbject. I our system we have a special memory called Heap memory. Heap memory will contain all objects. so I might have some address in heap memory the way to print the address is :

class computer:
    pass
c1=computer()

print(id(c1))

Output:
D:\Testing Document Sample>C:/Python312/python.exe "d:/Testing Document Sample/demo.py"
2509775964640     // this is an address
Enter fullscreen mode Exit fullscreen mode

What will be size of object?
It's depend upon the size of variable and number of variable

who allocate the memory to object ?
Constructor

we can also change the value of one object from different object

Example:

class computer:
    def __init__(self):
        self.name = "navin"
        self.age = 28

c1=computer()
c2=computer()

c1.name="rashi"
c2.age= 12

print (c1.name)
print (c2.name)
print (c1.age)
print (c2.age)

Output:
D:\Testing Document Sample>C:/Python312/python.exe "d:/Testing Document Sample/demo.py"
rashi
navin
28   
12

in the above code we can not only assign the different values to object explicitly but can change it also
Enter fullscreen mode Exit fullscreen mode

Why do we need this self?
To explain that lets take one more method called update which is used to update the age
When update is called it will update the age in class computer, but here is catch we have two objects which value needs to be changed, as we called it we have not passed any arguement c1 or c2.
So when calling update how do pointer know which object we are calling about weather c1 age or c2 age and that's where we are using self is directing to c1 and c2 based on calling by object. If we are using c1.update then in the bracket it will pass c1, then self will assign to c1, that's the important of self which is referring to the object.

class computer:
    def __init__(self):
        self.name = "navin"
        self.age = 28

    def update(self):
        self.age = 30


c1=computer()
c2=computer()

c1.name="rashi"
c2.age= 12

c1.update()      // this calls the update method. In the 

print (c1.name)
print (c2.name)
print (c1.age)
print (c2.age)


Output:
D:\Testing Document Sample>C:/Python312/python.exe "d:/Testing Document Sample/demo.py"
rashi
navin
30
12
Enter fullscreen mode Exit fullscreen mode

Let's compare the object for above: In below python don't know how to compare object. thus In this I will use seperate function to do that.

class computer:
    def __init__(self):
        self.name = "navin"
        self.age = 28

#   def update(self):
#      self.age = 30

    def compare(self,other):     // here c1 becomes self as object used to call and c2 become others passed as arguement
        if self.age==other.age:
            return true
        else:
            return false

c1=computer()
c1.age=30
c2=computer()

# if c1==c2:            // I don't want to compare address but want to compare their values(age) name doesn't matter

if c1.compare(c2):     // Since it's not an in build function thus we need to create it 
    print("They are same")

else:
    print("They are Different")

#c1.update()

print (c1.age)
print (c2.age)


Output:
D:\Testing Document Sample>C:/Python312/python.exe "d:/Testing Document Sample/demo.py"
They are Different
30
28
Enter fullscreen mode Exit fullscreen mode

Types of variable in OOPS

  1. Instance Variables (Object Attributes)

Definition: These variables are tied to a specific instance of a class. Each object of the class can have different values for these variables.
Scope: They are accessible only within the instance they belong to, not across all instances of the class.
How to Define: Defined inside the constructor method (init()) and are prefixed with self.

Example:

class Car:
    def __init__(self, model, color):
        self.model = model  # Instance variable
        self.color = color  # Instance variable

car1 = Car("Tesla", "Red")
car2 = Car("BMW", "Blue")

print(car1.model)  # Output: Tesla
print(car2.model)  # Output: BMW

Here, model and color are instance variables that are specific to each instance of the Car class.
Enter fullscreen mode Exit fullscreen mode
  1. Class Variables (Static Variables)

Definition: These are variables that are shared across all instances of the class. They are defined inside the class but outside of any instance methods.
Scope: They belong to the class itself and not to individual objects. Changes made to class variables affect all instances of the class.
How to Define: Declared within the class, but outside of any method. They are accessed using the class name or through any instance of the class.

Example:

class Car:
    wheels = 4  # Class variable

    def __init__(self, model, color):
        self.model = model
        self.color = color

car1 = Car("Tesla", "Red")
car2 = Car("BMW", "Blue")

print(Car.wheels)  # Output: 4 (Accessed through class)
print(car1.wheels)  # Output: 4 (Accessed through an instance)

Here, wheels is a class variable shared by all instances of the Car class. Both car1 and car2 will have access to this variable.
Enter fullscreen mode Exit fullscreen mode
  1. Instance Methods (Method Variables)

Definition: Variables declared inside instance methods (other than init) are method variables, and they are local to that specific method.
Scope: These variables are created and exist only within the method where they are defined. They are not accessible outside the method.
How to Define: Defined inside any method of a class using standard variable declaration without self.

Example:

class Car:
    def display_info(self):
        speed = 120  # Method variable
        print(f"Speed is {speed}")

car1 = Car()
car1.display_info()  # Output: Speed is 120

Here, speed is a method variable and is local to the display_info() method. It cannot be accessed outside this method.
Enter fullscreen mode Exit fullscreen mode
  1. Static Methods Variables

Definition: Variables defined inside static methods are local to that method, similar to instance methods. Static methods don’t have access to instance (self) or class variables unless passed explicitly.
Scope: Local to the static method.
How to Define: Defined inside a static method, typically declared with the @staticmethod decorator.

Example:

class Car:
    wheels = 4  # Class variable

    @staticmethod
    def show_description():
        description = "This is a car"  # Static method variable
        print(description)

Car.show_description()  # Output: This is a car

Here, description is a variable local to the static method show_description() and cannot be accessed outside this method.
Enter fullscreen mode Exit fullscreen mode
  1. Class Methods Variables

Definition: Variables defined inside class methods are similar to static method variables, but class methods can access and modify class variables. Class methods are defined using the @classmethod decorator.
Scope: Variables are local to the class method, but the method has access to class variables via the cls parameter.
How to Define: Declared within class methods, typically with the @classmethod decorator.

Example:

class Car:
    wheels = 4  # Class variable

    @classmethod
    def set_wheels(cls, count):
        cls.wheels = count  # Class method variable

Car.set_wheels(6)
print(Car.wheels)  # Output: 6

Here, count is a variable within the class method set_wheels, and the method can access and modify the class variable wheels.
Enter fullscreen mode Exit fullscreen mode

Key Difference :

  1. Instance Variables

Definition: Variables that are unique to each object (instance) of a class.
Scope: Available only within the instance they belong to.
Access: Accessed via self (i.e., self.variable_name).
Storage: Stored within each object; each instance has its own copy of instance variables.
Lifecycle: Created when an object is instantiated and destroyed when the object is deleted.
Modification: Each object can have its own unique values for instance variables.
Key Point: Instance variables are unique to each instance. For example, different Car objects can have different model and color.

  1. Class Variables

Definition: Variables that are shared across all instances of a class.
Scope: Belongs to the class itself and is shared by all instances.
Access: Accessed using ClassName.variable_name or via instances (though the preferred way is through the class name).
Storage: Stored in the class, not in the individual object instances.
Lifecycle: Created when the class is defined and exists for the lifetime of the class.
Modification: Modifying a class variable through the class affects all instances, whereas modifying it through an instance creates a new instance variable for that particular object.
Key Point: Class variables are shared across all instances. If wheels is changed through the class, it affects all instances unless overridden at the instance level.

  1. Method Variables (Local Variables)

Definition: Variables defined inside a method, and they are local to that method.
Scope: Available only within the method where they are defined.
Access: Can only be accessed within the method; not accessible outside the method or across instances.
Storage: Stored temporarily in the method call stack and are discarded once the method execution finishes.
Lifecycle: Created when the method is called and destroyed once the method finishes execution.
Modification: Each method call gets a fresh set of method variables.
Key Point: Method variables are local to the method and do not persist beyond the method's execution.

  1. Static Variables (Variables in Static Methods)

Definition: Variables defined inside a static method, local to the method itself, similar to method variables.
Scope: Confined to the static method where they are defined.
Access: Static methods do not have access to class or instance variables unless they are passed as arguments.
Storage: Stored temporarily during the execution of the static method.
Lifecycle: Created when the static method is called and destroyed once it finishes execution.
Modification: Modifying static method variables only affects that specific method execution.
Key Point: Static method variables are local to the static method and do not interact with class or instance variables unless explicitly passed.

Image description


Types of Methods in oops:

  1. Instance Methods:

Definition: Instance methods are the most common type of method in a class. They operate on instances of the class (i.e., objects) and can access or modify object attributes.
How to Define: Instance methods must have self as their first parameter, which refers to the instance of the class. They can access both instance variables and class variables.
Use Case: These methods are used to manipulate object-specific data.

Example:

class Car:
    def __init__(self, model, color):
        self.model = model  # Instance variable
        self.color = color  # Instance variable

    def display_info(self):  # Instance method
        print(f"Car model: {self.model}, Color: {self.color}")

car1 = Car("Tesla", "Red")
car1.display_info()  # Output: Car model: Tesla, Color: Red

Here, display_info is an instance method that operates on the instance car1 and accesses its instance variables (model and color).
Enter fullscreen mode Exit fullscreen mode
  1. Class Methods

Definition: Class methods are methods that operate on the class itself rather than on instances of the class. They can access or modify class variables but cannot modify instance variables.
How to Define: Class methods are defined using the @classmethod decorator, and they take cls as their first parameter, which refers to the class itself.
Use Case: These methods are used to work with class-level data and can be called without creating an instance of the class.

Example
class Car:
    wheels = 4  # Class variable

    @classmethod
    def change_wheels(cls, count):  # Class method
        cls.wheels = count

Car.change_wheels(6)
print(Car.wheels)  # Output: 6

In this example, change_wheels is a class method that modifies the class variable wheels and can be called on the class itself, not on individual objects.
Enter fullscreen mode Exit fullscreen mode
  1. Static Methods:

Definition: Static methods are methods that don’t operate on instances or the class itself. They do not take self or cls as their first parameter and cannot modify object state or class state. Static methods behave like regular functions but are bound to a class for organizational purposes.
How to Define: Static methods are defined using the @staticmethod decorator.
Use Case: Static methods are used when you need a function that logically belongs to the class but doesn’t need to access or modify any class or instance variables.

Example:

class Car:
    @staticmethod
    def is_motorized():  # Static method
        return True

print(Car.is_motorized())  # Output: True

Here, is_motorized is a static method that doesn’t rely on any class or instance data and can be called directly on the class.

Enter fullscreen mode Exit fullscreen mode

Key Differences:

Instance Methods:
Access both instance and class variables.
The self parameter allows access to object-specific data.

Class Methods:
Access only class variables.
The cls parameter allows access to class-level data and can modify it.

Static Methods:
Don’t access or modify class or instance variables.
Behave like regular functions, but are logically grouped inside a class.

Image description


Top comments (0)