Python is an object oriented programming language.
Almost everything in Python is an object.
A
Class is like a "blueprint" for creating objects or can be called as object factory.
Classes provide a means of bundling data and functionality together.
Classes are defined using keyword class.
The
simplest class definition is
class ClassName:
"class doc string "
statements
Examples:
# Worlds smallest class
class P: # define class name P
pass # pass is ust a plcae holder to create an empty class
class MyClass:
y = 20
class MyClass:
x = 10 # data
def fun1(self): # function
print('Hello class')
When we defined a class with a keyword class, a new namespace is created in the local scope(like for functions using def)
The class name is used to create a class object or instance of the class known as
instantiation
Let us create a class Foo
class Foo:
pass
We can call the class name Foo (which is a callable name object) like function call to create an instance or object of the class as follows
p = Foo()
"p" is a instance or object of Foo class and it has its reference
A class is a combination of data and methods (logics) which are called as attributes
The
attributes (data and methods) inside the class are class members.
When you define anything inside a class it becomes its attribute
class Foo:
x = 10
def func(self): # More on methods in next section
pass
Here "x" and "func()" are the attributes of class Foo
To access class attribute we use the following syntax
instance.attribute
For
example in the previous code, let us try to fetch the "x" attribute
class Foo:
x = 10
p = Foo()
print (p.x) # prints 10 - fetches attribute x - instance.attribute
We can also define functions inside a class. These functions defined inside classes are called as
methods.
The first argument (methods must always take at least one argument) is always the
instance of the class.
Example:
class Foo: # Define class object
def func(self): # Define class's method
print("Hello world")
p = Foo()
p.func() # calling the class method, prints "Hello world"
You can see that for func we have a function parameter self in function definition
def func(self)
This is because when we call a method using instance or object ,
the first the first argument automatically receives that particular object/instance
While
calling method p.func()
, the instance "p" is assigned to "self"
automatically by python itself
So p.func()
is same as Foo.funct(p)
as follows
p = Foo()
Foo.funct(p) # prints "Hello world"
Besides the first argument, other arguments will act like general function argument
Example:
class Foo:
def func(self, name, age):
print(name, age)
p = Foo()
p.func("John", 20) # prints - "John" 20
p.func("Doe", 30) # prints - "Doe" 30
Here "p" is assigned to "self" which is first argument.
The other
arguments we are passing while calling func , acts like positional arguments and
assigned to name and age respectively
You can use any name instead of self . However, it is a norm to use self.
Example:
class Foo:
def func(no_self): # no_self instead of self
print("Hello world")
p = Foo()
p.func() # prints "Hello world"
The attributes can be created/initialized/defined inside and outside of a class
Let us see
this example
class Employee:
def set_data(self, value):
self.data = value # Create a attribute sata and attach it self/instance
def display_data(self):
print(self.data)
p = Employee()
p.set_data(200) # Setting value to data for instance p
p.display_data()
p.data = 300 # Re-setting value to data for instance p
p.display_data() # Value of data is changed
p.new_data = 400 # Can get/set attributes outside calls too
print(p.new_data) # prints 400, Can get/set attributes outside calls too
Let us create multiple instances for a particular class.
We can do it by calling class name
multiple times
class Foo:
def func(no_self):
print("Hello world")
p = Foo()
e = Foo()
p.func()
e.func()
Let us see how the multiple instances works
There are tow kinds of attributes in python's
OOPs model i.e. class attributes and instance attributes
The top level assignments inside a class creates class attributes.
The class attributes are
shared by all the instances and any change to the class attribute will change the value across
in all the instances
But the instance attributes are attached to the instances and created by setting a attribute to the instance
Example:
# Class attributes
class Foo:
X = 10 # This is a class attribute
print(Foo.X) # prints 10 , Class attributes can be accessed using class name
p = Foo()
e = Foo()
# Class attributes shared by all instances
print(p.X) # prints 10 , Class attribute accessed by instance
print(e.X) # prints 10 , Class attribute accessed by instance
# Any change to class attribute will change its value across all instances
Foo.X = 20
print(p.X) # prints 20 , Value changed
print(e.X) # prints 20 , Value changed
When you assign a name/attribute to instance it becomes instance attribute
p.Y = 30
print(p.Y) # prints 30
print(e.Y) # AttributeError: 'Foo' object has no attribute 'Y'
Assigning a instance attribute using self inside a method
class Foo:
def set_value(self, value):
self.data = value # Setting a attribute to instance using self
p = Foo()
e = Foo()
p = set_value(10)
e = set_value(20)
print(p.data) # prints 10
print(e.data) # prints 20
The self in the class method set_value , is nothing but the copy of the instance.
Setting an
attribute to instance/object by assigning a value ( self.data = value
), creates an
instance attribute and attached it to the self means the particular object/instance.
Therefore
, the instance.data prints corresponding data attribute value
A constructor in python is a special type of method called to prepare an object or initialize the
variables for an object .
The class methods that starts with double underscore (__) are
special for python
One of the special method __init__() is the constructor in python.
The
__init__ method is invoked every time a object is created
(instantiation).
Example:
class Employee:
def __init__(self, name, age):
self.name = name # Initializing attribute name for instance
self.age = age # Initializing attribute age for instance
p = Employee("John", 20) # Creating instance "p", invokes __init__() and sets values for name and age for "p"
e = Employee("Doe", 30) # Creating instance "e", invokes __init__() and sets values for name and age for "e"
print(p.name, p.age) # prints "John", 20
print(e.name, e.age) # prints "Doe", 30
Once you define the __init__ method in a class, then while creating an object (when you call
Employee()), you can provide all the necessary parameters required for the object's
variables/attribute, because when we call Employee(), the python calls the __init__ method for
the created object automatically.
The __init__ method is similar as other class methods and
also takes self (instance) as first argument
Its not mandatory to defined __init__
method inside the class.