Python Classes and Objects
Tags: python, datascience, oop
Published: 2021-08-02 19:21:33

Python is an amazing programming language that supports both the functional programming paradigm and object-oriented programming paradigm.
Python's object-oriented programming system supports all the four fundamental features of a general OOPS framework: encapsulation, abstraction, inheritance and polymorphism.
######What is a Class and an Object?
* A **class** is a bundle of instance variables and related methods meant for defining a type of object viewed as a blueprint or a template of the objects.
* An **object** is an instance of a class with a specific set of attributes.

######Class Definition Syntax
To create a class, use the keyword **class** as shown below
```python
class ClassName:
    <statement-1>
    
    <statement-N>
```
######Object Types
**1.Class Objects**
From python documentation;
Class objects support two kinds of operations: attribute references and instantiation.
**Attribute references** use the standard syntax used for all attribute references in Python: *obj.name*.
*  Valid attribute names are all the names that were in the class’s namespace when the class object was created.
 Example:
```python
class Student:
    """A simple example class"""
    rollno = 12
    name = "Korir"
def messg(self):
        return 'New Session will start soon.'
```
* From the above example, **Student.roll_no**, **Student.name** are valid attribute references, returning an 12 and 'Korir' respectively.
**Student.messg** returns a function object.

* In Python **self** is a name for the first argument of a method which is different from ordinary function. Rather than passing the object as a parameter in a method the word self refers to the object itself.


**Instantiation** uses function notation.

To create an instance of a class, you call the class as if it were a function. The example below creates a new instance of the class and assigns this object to the local variable x.

```python
x = Student()
```
* The instantiation operation  creates an empty object. Therefore a class may define a special method named __init__(), like this:
```python
def __init__(self):
    self.data = []
```
 __ init __() method may have arguments for greater flexibility for example:
```python
class Student:
    """A simple example class"""
    def __init__(self,sroll, sname):
        self.r = sroll
        self.n = sname
    x = Student(10, 'Korir')
 x.r, x.n

```
Output
```python
(10, 'Korir')
```
**2.Instance Objects**
* The only operations understood by instance objects are attribute references. There are two kinds of valid attribute names: data attributes and methods.

**Data attributes** correspond to *instance variables* and need not be declared; like local variables, they spring into existence when they are first assigned to.

**A method** is a function that belongs to an object.
Valid method names of an instance object depend on its class. By definition, all attributes of a class that are function objects define corresponding methods of its instances.

From our example;
**x.messg** is a valid method reference, since **Student.messg** is a function.

**3.Method Objects**
* Usually, a method is called right after it is bound:
```python
x.messg()
```
* In the Student example, this will return the string 'New Session will start soon'.


######Class and Instance Attributes
**Instance attribute**
* An **instance attribute** is a Python variable belonging to only one object. 
* It is only accessible in the scope of the object and it is defined inside the constructor function of a class. 
For example:
```python
class Circle:
    def __ init __(self, radius):
        self.pi = 3.14159
        self.radius = radius

    def area(self):
        return self.pi * self.radius**2

    def circumference(self):
        return 2*self.pi * self.radius
```
* Both pi and radius are called instance attributes. Since they belong to a specific instance of the Circle class.

**Class Attribute**

* A class attribute is a Python Variable that belongs to a class rather than a particular object. 
* It is shared between all other objects of the same class and is defined outside the constructor function __ init __(self,…), of the class.
Example:
```python
class Circle:
    pi = 3.14159

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

    def area(self):
        return self.pi * self.radius**2

    def circumference(self):
        return 2 * self.pi * self.radius
```
* The above example defines pi as a class attribute
* You can access the class attribute via instances of the class or via the class name:
```python
object_name.class_attribute
class_name.class_attribute
```
From class attribute example;
```python
c = Circle(10)
print(c.pi)
print(Circle.pi)
```
Output will be;

```python
3.14159
3.14159
```

######Inheritance
* Like other object-oriented language, Python allows inheritance from a parent (or base) class as well as multiple inheritances in which a class inherits attributes and methods from more than one parent.
* The concept of inheritance provides an important feature to the object-oriented programming is reuse of code
* The syntax for single inheritance is:
```python
class DerivedClassName(BaseClassName):
    <statement-1>
    
    <statement-N>
```
* Below is a simple example of single inheritance in python.
```python
class Parent():
       def first(self):
           print('first function')
 
class Child(Parent):
       def second(self):
          print('second function')
 
ob = Child()
ob.first()
ob.second()
```
Here's the output:
```python
first function
second function
```
* From the above code, you can access the parent class function using the child class object.

**Sub-classing** 
* Calling a constructor of the parent class by mentioning the parent class name in the declaration of the child class is known as sub-classing. A child class identifies its parent class by sub-classing.

* Other types of inheritance are; 

**Multiple Inheritance**-When a child class inherits from more than one parent class.
**Multilevel Inheritance**-When a child class becomes a parent class for another child class.
**Hybrid Inheritance**- involves multiple inheritance from the same base or parent class. 
**Hierarchical Inheritance**-involves multiple inheritance taking place in a single program.