The basic idea behind an object-oriented programming (OOP) is to combine both data and associated procedures (known as methods) into a single unit which operate on the data. Such a unit is called an object.
Python is an object-oriented language, everything in Python is an object.
We have already worked with some objects in Python, (See Python data type chapter) for example strings, lists are objects defined by the string and list classes which are available by default into Python. Let's declare two objects a string and a list and test their type with type() function.
As string1 is an object, strings "Good Morning" can produce an uppercase or lowercase version of themselves calling upper() and lower() methods associated with the string. Check it in the Python IDLE.
Before introducing classes we must discuss something about local variables, global statement, and a nonlocal statement as well as Namespaces and scope rules.
When a variable is declared inside a function, that variable is accessible only from that function or statements block where it is declared. The variable has no relation with any other variable with the same name declared outside the function, therefore the variable is local to the function. See the following example.
# python-local-variable.py def function_local(a): print('a is -> ',a) a = 50 print('After new value within the function a is -> ',a) a = 100 function_local(40) print('Value of a is ->',a)
a is -> 40
After new value within the function a is -> 50
Value of a is -> 100
Line No.- 2 : Declared a function function_local(a) with a parameter
Line No.- 3 : Print 'a' uses the value of the parameter. [The value of a is now 100 as we assign a to 100 (Line No. 6) before executing the function (Line No. 7).]
Line No.- 4 : Assign the value 50 to 'a'.
Line No.- 5 : Again print 'a', as a is local within the function, therefore, the value of a is now 50.
Line No.- 8 : This is the last print statement and 'a' becomes 100. So far what we have done within the function which has no effect on the function. This is called the scope of the variable.
The purpose of the global statement is to assign a value to a variable which is declared outside the function. Free variables (See Line No. 06 in the previous example) may refer to globals without declaring global. The syntax of global statement is -> global var_name1, var_name2, ..
See the following example :
# python-global-variable.py def function_local(): global a print('a is -> ',a) a = 50 print('After new value within the function a is -> ',a) a = 100 function_local() print('Value of a is ->',a)
a is -> 100
After new value within the function a is -> 50
Value of a is -> 50
Line No.- 3 : The variable 'a' is declared as a global variable, therefore the value of a is now 100.
Line No.- 5 : Assign the value 50 to 'a' and it will hold same value inside and outside the function unless we assign a new value.
The nonlocal statement is used to rebind variables found outside of the innermost scope. See the following example without a nonlocal statement.
def outside(): a = 10 def inside(): a = 20 print("Inside a ->", a) inside() print("outside a->", a) outside()
In the above example the first print() statement simply print the value of 'a', which is 20 as 'a' is local within inside() function. The second print() statement prints the value 'a', which is 10 as the inside() function has no effect. Now we introduce a nonlocal statement in inside() function and the code will be:
def outside(): a = 10 def inside(): nonlocal a a = 20 print("The value of a in inside() function - ", a) inside() print("The value of a in outside() function - ", a) outside()
The second print() statement prints the value 'a', which is 20 as the variable 'a' is rebound..
Python Scopes and Namespaces
In general, a namespace is a naming system to create unique names. In daily experience, we see railway stations, airports, the capital of various states, the directory structure of filesystems have unique names. As of other programming language Python uses namespaces for identifiers.
A namespace is a mapping from names to objects.
- For example 'a' maps to [1, 2, 3] or 'a' maps to the value 25.
- Most namespaces currently implemented as Python dictionaries (containing the names and values of the objects).
- Names in different namespaces have absolutely no relationship (e.g. the variable 'a' can be bound to different objects in different namespaces).
- Examples of the namespace : The global name of a module, local names in a function invocation, built-in names (containing functions such as min()), attributes of an object.
Python creates namespaces at different times.
- The built-in namespace is created when Python interpreter starts and is never deleted.
- The global namespace for a module is created when the module is called and last until the interpreter quits.
- The local namespace for a function is created when the function is called and deleted when the function returns.
A scope is a textual region of a Python program where a namespace is directly accessible. The scopes in python are as follows:
- The local scope, searched first, contains the local name.
- Enclosing scope (in an enclosing function) contains non-local and non-global names.
- The current module’s global names.
- The outermost scope is the namespace containing built-in names.
Defining a class
In object oriented programming classes and objects are the main features. A class creates a new data type and objects are instances of a class which follows the definition given inside the class. Here is a simple form of class definition.
A class definition started with the keyword 'class' followed by the name of the class and a colon.
The statements within a class definition may be function definitions, data members or other statements.
When a class definition is entered, a new namespace is created, and used as the local scope.
Creating a Class
Here we create a simple class using class keyword followed by the class name (Student) which follows an indented block of segments (student class, roll no., name).
#studentdetails.py class Student: stu_class = 'V' stu_roll_no = 12 stu_name = "David"
There are two kind of operations class objects supports : attribute references and instantiation. Attribute references use the standard syntax, obj.name for all attribute references in Python. Therefore if the class definition (add a method in previous example) look like this
#studentdetails1.py class Student: """A simple example class""" stu_class = 'V' stu_roll_no = 12 stu_name = "David" def messg(self): return 'New Session will start soon.'
then Student.stu_class, Student.stu_roll_no, Student.stu_name are valid attribute reference and returns 'V', 12, 'David'. 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. For example if a method is defined as avg(self, x, y, z), it should be called as a.avg(x, y, z). See the output of the attributes in Python Shell.
__doc__ is also a valid attribute which returns the docstring of the class.
There are many method names in Python which have special importance. A class may define a special method named __init__ which does some initialization work and serves as a constructor for the class. Like other functions or methods __init__ can take any number of arguments. The __init__ method is run as soon as an object of a class is instantiated and class instantiation automatically invokes __init__() for the newly-created class instance. See the following example a new, initialized instance can be obtained by:
#studentdetailsinit.py class Student: """A simple example class""" def __init__(self, sclass, sroll, sname): self.c = sclass self.r = sroll self.n = sname def messg(self): return 'New Session will start soon.'
The concept of inheritance provides an important feature to the the object-oriented programming is reuse of code. Inheritance is the process of creating a new class (derived class) to be based on an existing (base class) one where the new class inherits all the attributes and methods of the existing class. Following diagram shows the inheritance of a derived class from the parent (base) class.
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. See the single and multiple inheritance syntaxes :
In a company Factory, staff and Office staff have certain common properties - all have a name, designation, age etc. Thus they can be grouped under a class called CompanyMember. Apart from sharing those common features, each subclass has its own characteristic - FactoryStaff gets overtime allowance while OfficeStaff gets traveling allowance for an office job. The derived classes ( FactoryStaff & OfficeStaff) has its own characteristic and, in addition, they inherit the properties of the base class (CompanyMember). See the example code.
# python-inheritance.py class CompanyMember: '''Represents Company Member.''' def __init__(self, name, designation, age): self.name = name self.designation = designation self.age = age def tell(self): '''Details of an employee.''' print('Name: ', self.name,'\nDesignation : ',self.designation, '\nAge : ',self.age) class FactoryStaff(CompanyMember): '''Represents a Factory Staff.''' def __init__(self, name, designation, age, overtime_allow): CompanyMember.__init__(self, name, designation, age) self.overtime_allow = overtime_allow CompanyMember.tell(self) print('Overtime Allowance : ',self.overtime_allow) class OfficeStaff(CompanyMember): '''Represents a Office Staff.''' def __init__(self, name, designation, age, travelling_allow): CompanyMember.__init__(self, name, designation, age) self.marks = travelling_allow CompanyMember.tell(self) print('Traveling Allowance : ',self.travelling_allow)
Now execute the class in Python Shell and see the output.