In all the program we wrote till now, we have designed our program around the functions i.e. blocks of the statement which manipulate the data. This is call the procedure-oriented way of programming, there is another way of organizing your program which is to combine data and functionality and wrap it insdie something called an object. This is called the object oriented programming.
Most of the time you can use procedural programming, but when writing large programs or have a problem that is better suited to this method, you can use object oriented programming techniques.
Did you remember this code snippet in the section Python Datatypes?
You see that we have all our data types in python have a keyword class in front of it.
Everything is in objects because everything in python is a built-in class and we will use different methods on each of these classes.
Object have methods and attributes that you can access with the .methods like .count(), .capitalize() and many more..
strDataType = "hello world" listDataType = ["apple", "banana", "cherry"] print(strDataType.capitalize()) #Output: Hello world print(listDataType.count('apple')) #Output: 1
Classes and objects are the two main aspects of object oriented programming. A class creates a new type where objects are instance of the class.
A Class is created using the class keyword. The fields and methods of the valss are listed in an indented block.
class MyClass: pass # An empty block
obj1 = MyClass() print(obj1) #Output: <__main__.MyClass object at 0x000001A147D68D88>
class MyClass: pass # An empty block obj1 = MyClass() print(obj1) #Output: <__main__.MyClass object at 0x000001A147D68D88>
We create a new class using the class statement and the name of the class. This is followed by an indented block of the statements which form the body of the class. In this case, we have an empty block which is indicated the pass statement.
Next, we create an object/instance of this calls using the name of the class followed by a pair of parentheses. (We will learn more about instantiation in the next section). For our verification, we confirm the type of the variable by simply printing it. It tells us that we have an instance of the MyClass class in the __main__ module.
You could notice that the address of the computer memory where you object is stored is also printed. The address will have a different value on your computer since Python can stoer the object wherever it finds space.
Class methods have only one specific difference form ordinary functions - they must have an extra first name that has to ve added to the beginning of the parameter list, but you do not give a value for this parameter when you call the method, python will provide it. This particular variable refers to the object itself, and by convention, it is given the name self.
Although, you can give any name for this parameter, it is strongly recommended that you use the name self - any other name is definitely frowned upon. There are many advantages to using a standard name - any reader of your program will immediately recognize it and even specialized IDEs(Integrated Development Environments) can help you if you use self.
You must be wondering how Python gives the value for self and why you don't need to give a value for it. An example below will make this clear. Say you have a call MyClass and an instance of this class called myobject(object name). When you call a method of this object as myobject.method(arg1, arg2), this is automatically converted by Python into MyClass.method(self, arg1, agr2) - This is all the special self is about.
There are many method names which have special significance in Python classes. We will see the significance of the __init__ method now. The __init__ method is run as soon as an object of a class is instantiated. This method is useful to do any initialization you want to do with your object.
let's see some example below
class MyClass: def __init__(self, a, b): self.a = a #attribute self.b = b #attribute def sum(self): return self.a + self.b def mul(self): return self.a * self.b myobject = MyClass(10, 20) print(myobject.sum()) #Output: 30 print(myobject.mul()) #Output: 200 myobject = MyClass(100, 200) print(myobject.sum()) #Output: 300 print(myobject.mul()) #Output: 20000
Here, we define the __init__ method as taking a parameter name(along with the usual self), we just create a new fields(a & b). Notice there are two diffent variables(self and a,b) even though they are both called 'a' & 'b'.
There is not problem because the dotted notation self.a & self.b means that there is something called 'a' & 'b' that is part of the boject called 'self' and the other name is a local variables. Since we explicitly indicate which variable 'a' & 'b' we are referring to, there is no confusion.
If you have a method which takes no arguments, then you still have to have one argument- the self.
class MyClass: def sayHi(self): print("Hello, how are you?") myobject = MyClass() myobject.sayHi() #Output: Hello, how are you? #This short example can also be written as MyClass().sayHi() #Output: Hello, how are you?
Class object attributes are unlike attribute.
It is a static value across all the instance(or object) of classes.
class MyClass: Total_Subject = 5 #Class Oject Attribute def __init__(self, a, b, c, d, e): self.a = a #attribute self.b = b #attribute self.c = c #attribute self.d = d #attribute self.e = e #attribute def Total(self): return self.a + self.b + self.c + self.d + self.e def TotalAverage(self): return self.Total()/ self.Total_Subject StudentObj1 = MyClass(70, 80, 100, 40, 50) print(StudentObj1.Total()) #Output: 340 print(StudentObj1.TotalAverage()) #Output: 68.0 StudentObj2 = MyClass(80, 90, 100, 60, 70) print(StudentObj1.Total_Subject) #Output: 5 print(StudentObj2.Total_Subject) #Output: 5
In the above example, the class object attribute StudentObj1.Total_Subject & StudentObj2.Total_Subject prints the static value 5 across all instance of the class.
class MyClass: def __init__(self, a, b): self.a = a self.b = b def sum(self): return self.a + self.b def mul(self): return self.a * self.b myobject = MyClass(10, 20) print(myobject.sum()) #Output: 30 print(myobject.mul()) #Output: 200 myobject.a = 100 myobject.b = 100 print(myobject.sum()) #Output: 200 myobject.a = 20 myobject.b = 20 print(myobject.mul()) #Output: 400
There is another special method __del__ which is called when an object is going to die i.e. it is no longer being used and is being returned to the computer system for reusing that piece of memory.
class MyClass: def __init__(self, a, b): self.a = a self.b = b def sum(self): return self.a + self.b def mul(self): return self.a * self.b def __del__(self): "I am dying." myobject = MyClass(10, 20) print(myobject.sum()) #Output: 30 print(myobject.mul()) #Output: 200
The __del__ method is run when the object us no longer in use and there is no guarantee when that method will be run. If you want to explicitly see it in action, we have to use the del statement which is what we have done here.
class Person: def __init__(self, name, age): self.name = name self.age = age def myfunc(self): print("my name is " + self.name) obj = Person("Ram", 36) obj.age = 40 del obj.age print(obj.age)
AttributeError: 'Person' object has no attribute 'age'
There are four important pillar in OOPs. They are,
We will see these topics in detail in the upcoming section...
If you have any doubts or queries related to this chapter, get them clarified from our Python Team experts on ibmmainframer Community!