Tuesday, April 28, 2015

Learn Python by example


Create a simple class in Python


class Employee(object):
"""Encapsulate employee information here"""
def __init__(self, name, age):
super(Employee, self).__init__()
self.name = name
self.age = age

def printDetails(self):
print('Name is ' + self.name)
print('Age is ' + str(self.age))

def __del__(self):
class_name = self.__class__.__name__
print(class_name + ' destroyed')

tempEmp = Employee('Krishnan', 35)
tempEmp.printDetails()

All methods, have a default first argument of self. __init__ is synonymous to constructors in C++/Java/C# world. Initialize your properties in init method

__del__ is synonymous to destructor. Dereference your objects here

You can access the properties of the class, from within the class using "self" keyword. Although you'll be able to access the same properties from outside the class like the following
print('Name of employee: ' + tempEmp.name)

I'd prefer few other ways of doing the same
getattr(obj, name[, default]) - get an attribute
hasattr(obj,name) - check to see if an attribute is defined
setattr(obj,name,value) - Set value on an attribute, if attribute does not exist, it is created on this instance
delattr(obj, name) - Delete's the attribute from the instance

class Employee(object):
"""Encapsulate employee information here"""
def __init__(self, name, age):
super(Employee, self).__init__()
self.name = name
self.age = age

def printDetails(self):
print('Name is ' + self.name)
print('Age is ' + str(self.age))

tempEmp = Employee('Krishnan', 35)
if hasattr(tempEmp, 'age'):
print('Age of employee is ' + str(getattr(tempEmp, 'age', 10)))

if hasattr(tempEmp, 'salary') == False:
setattr(tempEmp, 'salary', 1000000)

if hasattr(tempEmp, 'salary'):
print('Salary of employee is ' + str(getattr(tempEmp, 'salary', 0)))

Garbage collection


Garbage Collection in Python is simple and easy to follow. When an object is created, assigned a new name or added to a container, reference count is increased. When an object is removed using 'del' keyword or goes out of scope, its reference count is decreased. When the count reaches '0', it will be garbage collected


Inheritence

Sample for simple inheritance in Python is shown below

class Employee(object):
"""Encapsulate employee information here"""
def __init__(self, name, age):
super(Employee, self).__init__()
self.name = name
self.age = age

def printDetails(self):
print('Name is ' + self.name)
print('Age is ' + str(self.age))

def __del__(self):
class_name = self.__class__.__name__
print(class_name + ' destroyed')

class Manager(Employee):
"""docstring for Manager"""
def __init__(self, name, age, department):
super(Manager, self).__init__(name, age)
self.department = department

def printDetails(self):
super(Manager, self).printDetails()
print('Works for: ' + self.department)

def __del__(self):
class_name = self.__class__.__name__
print(class_name + ' destroyed')

tempEmp = Manager('Krishnan', 35, 'IT')
tempEmp.printDetails()
if hasattr(tempEmp, 'age'):
print('Age of employee is ' + str(getattr(tempEmp, 'age', 10)))

if hasattr(tempEmp, 'salary') == False:
setattr(tempEmp, 'salary', 1000000)

if hasattr(tempEmp, 'salary'):
print('Salary of employee is ' + str(getattr(tempEmp, 'salary', 0)))

We can easily extend this to Multi-level inheritence. Note how super class methods are invoked. If you need to make any decision based on instance methods, you could use any of the following methods

isinstance(obj, Class) - Checks to see if obj is an instance of 'Class'
issubclass(sub, sup) - Checks to see of 'sub' is a subclass of super class'sup'

Method printDetails in Manager is the overriden method, hence we need to do super.printDetails.

If you are wondering how to hide properties in a class use '__' syntax. In the following example, you'll notice employeeIdentificationCode in Employee class that is a private property. It cannot be accessed anywhere but Employee class. It will not be accessible in Manager class too.

#! /Library/Frameworks/Python.framework/Versions/3.4/bin/python3

class Employee(object):
"""Encapsulate employee information here"""
__employeeIdentificationCode = 0
def __init__(self, name, age, empNo):
super(Employee, self).__init__()
self.name = name
self.age = age
self.empNo = empNo
self.__employeeIdentificationCode = empNo + 10


def printDetails(self):
print('Emp No: ' + str(self.empNo))
print('Name is ' + self.name)
print('Age is ' + str(self.age))
print('Personal Identification Code: ' + str(self.__employeeIdentificationCode))


def __del__(self):
class_name = self.__class__.__name__
print(class_name + ' destroyed')

class Manager(Employee):
"""docstring for Manager"""
def __init__(self, name, age, empNo, department):
super(Manager, self).__init__(name, age, empNo)
self.department = department

def printDetails(self):
super(Manager, self).printDetails()
print('Works for: ' + self.department)

def __del__(self):
class_name = self.__class__.__name__
print(class_name + ' destroyed')

tempEmp = Manager('Krishnan', 35, 100,'IT')
tempEmp.printDetails()
if hasattr(tempEmp, 'age'):
print('Age of employee is ' + str(getattr(tempEmp, 'age', 10)))

if hasattr(tempEmp, 'salary') == False:
setattr(tempEmp, 'salary', 1000000)

if hasattr(tempEmp, 'salary'):
print('Salary of employee is ' + str(getattr(tempEmp, 'salary', 0)))


Operator Overloading

You can do operator overloading by overriding methods like __add__ and __sub__

Class attributes

More often then not, we'll need static variables in class. Here' how we do it. Check out variable 'VectorCount' in the sample below

#! /Library/Frameworks/Python.framework/Versions/3.4/bin/python3

class Vector(object):
"""docstring for Vector"""
vectorCount = 0

def __init__(self, real, imaginary):
super(Vector, self).__init__()
self.real = real
self.imaginary = imaginary
Vector.vectorCount += 1

def showEquation(self):
print('Equation ' + str(Vector.vectorCount))
print (str(self.real) + 'x + ' + str(self.imaginary))

def __del__(self):
class_name = self.__class__.__name__
print(class_name + ' destroyed')

vect1 = Vector(10, 11)
vect1.showEquation()

vect2 = Vector(9, 12)
vect2.showEquation()

vect3 = Vector(8, 13)
vect3.showEquation()

vect4 = Vector(7, 14)
vect4.showEquation()


Class information/introspection

There are a lot of times, we will like to do some introspection on a class. Be it a high level documentation, dump of a class, etc. If you ever wanted such, here's how we do it
#! /Library/Frameworks/Python.framework/Versions/3.4/bin/python3

class Vector(object):
"""docstring for Vector"""
vectorCount = 0
__vectorID = 0

def __init__(self, real, imaginary):
super(Vector, self).__init__()
self.real = real
self.imaginary = imaginary
Vector.vectorCount += 1
self.__vectorID += 1

def showEquation(self):
print('Equation ' + str(Vector.vectorCount))
print (str(self.real) + 'x + ' + str(self.imaginary))

def __del__(self):
class_name = self.__class__.__name__
print(class_name + ' destroyed')


def printClassInformation():
print(Vector.__doc__)
print('Class under introspection: ' + Vector.__name__)
print('Class information: ' + str(Vector.__dict__))

vect1 = Vector(10, 11)
vect1.showEquation()

vect2 = Vector(9, 12)
vect2.showEquation()

vect3 = Vector(8, 13)
vect3.showEquation()

vect4 = Vector(7, 14)
vect4.showEquation()

printClassInformation()

__doc__ prints the comments in the class
__name__ prints the name of the class
__dict__ prints a dump of class. Try out a dump of a class with private properties and class properties. You are in for surprise
__bases__ prints inheritence hierarchy of the class
__module__ prints the module/function information

File operations

#!/usr/bin/python
import os

#FILE_NAME='Deploy_ios_application_to_device.txt'
FILE_NAME='Sample.txt'
# Identify current location
os.getcwd()
os.chdir('/Users/sriramramakrishnan/Private')

try:
# open the file that needs to be read
data = open(FILE_NAME)

# read line by line, until end
for line in data:
line = line.strip()
print(line)

# after reading the file, make sure you close it
data.close()
# there it ends
except IOError as err:
print('ERROR: failed to open file')
print('Error description: ' + str(err))
finally:
if 'data 'in locals():
print('File is open and should be closed!')
data.close()

No comments: