Object Oriented Programming (OOP) is a programming paradigm that uses objects and their interactions to design applications and computer programs. (Wikipedia)
There are some basic programming concepts in OOP:
$\bf Class: $ A user-defined prototype for an object that defines a set of attributes that characterize any object of the class. The attributes are data members (class variables and instance variables) and methods, accessed via dot notation.
$\bf Class\ variable: $ A variable that is shared by all instances of a class. Class variables are defined within a class but outside any of the class's methods. Class variables are not used as frequently as instance variables are.
$\bf Data\ member: $ A class variable or instance variable that holds data associated with a class and its objects.
$\bf Function\ overloading: $ The assignment of more than one behavior to a particular function. The operation performed varies by the types of objects or arguments involved.
$\bf Instance\ variable: $ A variable that is defined inside a method and belongs only to the current instance of a class.
$\bf Inheritance: $ The transfer of the characteristics of a class to other classes that are derived from it.
$\bf Instance: $ An individual object of a certain class. An object obj that belongs to a class Circle, for example, is an instance of the class Circle.
$\bf Instantiation: $ The creation of an instance of a class.
$\bf Method : $ A special kind of function that is defined in a class definition.
$\bf Object: $ A unique instance of a data structure that's defined by its class. An object comprises both data members (class variables and instance variables) and methods.
$\bf Operator\ overloading: $ The assignment of more than one function to a particular operator.
In [ ]:
import sys
def function(): pass
print type(1)
print type("")
print type([])
print type({})
print type(())
print type(object)
print type(function)
print type(sys)
### A "Class" is a code structure that contains ...
### One way to think of these is:
The previous objects were mostly built-in objects of the Python programming language. The user defined objects are created using the class keyword. The class is a blueprint that defines a nature of a future object. From classes we construct instances. An instance is a specific object created from a particular class. For example, Phydoux might be an instance of a Dog class.
In [ ]:
# first.py
class First:
pass
fr = First()
print type(fr)
print type(First)
This is our first class. The body of the class is left empty for now. It is a convention to give Classes a name that starts with a capital letter.
Here we see that fr is an instance object and First is a class object.
Inside a class, we can define attributes and methods. An attribute is a characteristic of an object. This can be for example the wavelength of a sensor. A method defines operations that we can perform with our objects. A method might define a turning the sensor on and collecting an image. Technically, attributes are variables and methods are functions defined inside a class.
In [ ]:
class Dog:
def __init__(self, name):
self.name = name
phydoux = Dog('Phydoux')
lucky = Dog('Lucky')
print phydoux.name
print lucky.name
In this code example, we have a Dog class. The special method init() is called automatically right after the object has been created.
Each method in a class definition begins with a reference to the instance object . It is by convention named self. There is nothing special about the self name. We could name it this, for example. The name is the argument. The value is passed during the class instantiation.
self.name = name
Here we pass an attribute to an instance object.
phydoux = Dog('Phydoux')
lucky = Dog('Lucky')
Here we instantiate two objects: dogs Phydoux and Lucky. The number of arguments must correspond to the __init__()
method of the class definition. The 'Phydoux'
and 'Lucky'
strings become the name parameter of the __init__()
method.
The attributes can be assigned dynamically, not just during initialization. This shows the next example.
In [ ]:
class Dynamic:
pass
d = Dynamic()
d.name = "Dynamic"
print d.name
We define and create an empty Dynamic class. The line of code:
d.name = "Dynamic"
creates a new name attribute, which is very different that other languages where you have to declaire the variables up front.
Methods are functions defined inside the body of a class. They are used to perform operations with the attributes of our objects. Methods are essential in encapsulation concept of the OOP paradigm. For example, we might have a connect() method in our AccessDatabase class. We need not to be informed how exactly the method connect connects to the database. We only know that it is used to connect to a database. This is essential in dividing responsibilities in programming, especially in large applications.
In [ ]:
class Circle:
pi = 3.141592
def __init__(self, radius=1):
self.radius = radius
def area(self):
return self.radius * self.radius * Circle.pi
def setRadius(self, radius):
self.radius = radius
def getRadius(self):
return self.radius
c = Circle()
c.setRadius(5)
print c.getRadius()
print c.area()
In the code example, we have a Circle class. We define three new methods.
area()
setRadius()
getRadius()
The area()
method returns the area of a circle. The getRadius()
method returns the current radius.
In [ ]:
class Book:
def __init__(self, title, author, pages):
print "A book is created"
self.title = title
self.author = author
self.pages = pages
def __str__(self):
return "Title:%s , author:%s, pages:%s " % \
(self.title, self.author, self.pages)
def __len__(self):
return self.pages
def __del__(self):
print "A book is destroyed"
book = Book("Inside Steve's Brain", "Leander Kahney", 304)
print book
print len(book)
del book
In our code example, we have a book class. Here we introduce four special methods. The __init__()
, __str__()
, __len__()
and the __del__()
methods. You can imagine how similar special methods can be used to implement __add__()
, __sub__()
, etc.
The inheritance is a way to form new classes using classes that have already been defined. The newly formed classes are called derived classes, the classes that we derive from are called base classes. Important benefits of inheritance are code reuse and reduction of complexity of a program. The derived classes (descendants) override or extend the functionality of base classes (ancestors).
In [ ]:
class Animal:
def __init__(self):
print "Animal created"
def whoAmI(self):
print "Animal"
def eat(self):
print "Eating"
class Dog(Animal):
def __init__(self):
Animal.__init__(self)
print "Dog created"
def whoAmI(self):
print "Dog"
def bark(self):
print "Woof!"
d = Dog()
d.whoAmI()
d.eat()
d.bark()
In this example, we have two classes: Animal and Dog. The Animal is the base class, the Dog is the derived class. The derived class inherits the functionality of the base class. It is shown by the eat() method. The derived class modifies existing behaviour of the base class, shown by the whoAmI() method. Finally, the derived class extends the functionality of the base class, by defining a new bark() method.
We put the ancestor classes in round brackets after the name of the descendant class. If the derived class provides its own __init__()
method, it must explicitly call the base class __init__()
method.
The polymorphism is the process of using an operator or function in different ways for different data input. In practical terms, polymorphism means that if class B inherits from class A, it doesn’t have to inherit everything about class A; it can do some of the things that class A does differently.
In [ ]:
class Animal:
def __init__(self, name=''):
self.name = name
def talk(self):
pass
class Cat(Animal):
def talk(self):
print "Meow!"
class Dog(Animal):
def talk(self):
print "Woof!"
a = Animal()
a.talk()
c = Cat("Missy")
c.talk()
d = Dog("Rocky")
d.talk()
Here we have two species: a dog and a cat. Both are animals. The Dog class and the Cat class inherit the Animal class. They have a talk() method, which gives different output for them.
In computer programming languages, encapsulation is used to refer to one of three related but distinct ideas:
Some programming language researchers and academics use the first meaning alone or in combination with the second as a distinguishing feature of object-oriented programming, while other programming languages which provide lexical closures view encapsulation as a feature of the language orthogonal to object orientation.
The second definition is motivated by the fact that in many OOP languages hiding of components is not automatic or can be overridden; thus, information hiding is defined as a separate notion by those who prefer the second definition.
Python doesn’t have any mechanisms that would effectively restrict you from accessing a variable or calling a member method. All of this is a matter of culture and convention.
If an identifier is only preceded by one underscore character, it is a protected member. Protected members can be accessed like public members from outside of class. It can be seen in the following example:
In [ ]:
class Encapsulation(object):
def __init__(self, a, b, c):
self.public = a
self._protected = b
self.__private = c
The following interactive sessions shows the behaviour of public, protected and private members:
In [ ]:
x = Encapsulation(11,13,17)
In [ ]:
x.public
In [ ]:
x._protected
In [ ]:
x._protected = 23
In [ ]:
x._protected
In [ ]:
x.__private
Note, that if you try accessing __private from outside the class, you’ll get an error. But you can still stumble upon something like this:
In [ ]:
>>> x._Encapsulation__private
As mentioned above this is considered bad practice, and if caught you will be subject to being held up to small children as an example of how NOT to behave.
In [ ]: