Rapid Python Programming

Chapter 6

OOP - Object Oriented Programming

So far you have been creating programs in a procedural way using functions and blocks of statements. With a slight twist you can wrap your functions into an object, and advance to understanding the concept of the object oriented programming paradigm. Without realizing it, you have already been using certain aspects of object oriented programming but in a procedural way.

6.1.2 Objects

By now, you are familiar with features such as strings, integers, dictionaries, and functions. These are all objects. The string object has methods which provide additional ways to manipulate the string. Using the ’↓dot syntax’ you can access the objects attributes such as “string A.↓lower()”. So from the beginning we have been accessing the methods of each of our objects. You can also create new instance of the object known as ↓instantiation. In essence they are ’datatypes’ and can be tested with a built in function ’type’.

>>> dat=’a string’
>>> print ↓type(’dat’)
<type ’str’>

The ’dot syntax’ would apply easily. Checking your ’type’, you find it to be a class string object or ’str(object)’. Here is an example of a class object easily tested using ’type’. Don’t forget you will still need to indent your text after the class statement. Reminder: There are no spaces between the underscore symbols.

Finally as always, pay ATTENTION to indentation!

>>> class orphan():
...
def __init__(self):
	...
	self.arg1=arg1
	...
>>> print type(orphan)
<type ’classobj’>
>>>

Objects store data by using variables that belong to the object. The variables belong to the object or class as fields. Functions work the same, they are called methods of a class. So basically fields and methods are attributes of a class.

6.1.3 Self and Class

A class is created by using the keyword ’↓class’ like “class orphan():”. What makes this different from a function or (method) is the name ↓specifier of ↓’self’. The value of ’self’ is the name itself which refers to the object itself. Think of ’self’ like a pointer in C++. If you have a class called ’blahClass’ and an instance of the class called ’blahObj’. You call the method of the object like ’blahObj.method(arg1)’, python will convert it as “BlahClass.method(blahObj,arg1)”. Even if you have a method with no arguments, you still have to define a method with the self argument. Here is a practical example:

#classhello.py
class hello:
	def blah(self):
		print "Hello world, again"
a=hello() # pointer location in memory
a.blah() # print method of class
hello().blah() # another way to access the class

As you can see self exists and it takes no parameters.

Results:

Hello world, again
Hello world, again

6.1.4 __init__

The ’__init__’ method initializes as soon as the object is instantiated. We don’t call the method ’__init__’ (our constructor). We merely pass it arguments. For example:

Pay ATTENTION to indentation!

#classinit.py
class hello:
	def __init__(self,name):
		self.name=name
	def blah(self):
		print "Hello world, my name is",self.name
a=hello(’William’)
a.blah()

Results:

Hello world, my name is William

Now pass more arguments:

#name.py
class hello:
	def __init__(self,l,f):
		self.last=l
		self.first=f
	def blah(self):
		print "My first name is", self.first
		print "My last name is", self.last
a=hello(’Doe’, ’John’)
a.blah()

Results:

My first name is John
My last name is Doe

Here is another example:

#shop.py
class cart():
	def __init__(self):
		self.food = "beans"
		self.amt = 0
	def buyfood(self,amt):
		self.amt += amt
		print "You purchased" ,amt,"cans",self.food
checkout = cart()
checkout.buyfood(5)

Results:

You purchased 5 cans beans

6.1.5 Destructor

Here is a small example of a destructor. Though I hardly ever use destructors in my code, they do exist and can be useful.

#des.py
class Des():
	def __init__(self, x):
		self.x = x
		print self.x, ’ready’
	def __del__(self):
		print self.x-1, ’destroyed’
x = Des(1)

Results:

1 ready
0 destroyed

6.1.6 Inheritance

You can develop a class that inherits the values of another class. This example shows you how to inherit the ’first()’ class in the ’second()’ class as ’class second(first)’:

Pay ATTENTION to indentation!

Here is a small example of a destructor. Though I hardly ever use destructors in my code, they do exist and can be useful.

#des.py
class Des():
	def __init__(self, x):
		self.x = x
		print self.x, ’ready’
	def __del__(self):
		print self.x-1, ’destroyed’
x = Des(1)

Results:

1 ready
0 destroyed

6.1.6 Inheritance

You can develop a class that inherits the values of another class. This example shows you how to inherit the ’first()’ class in the ’second()’ class as ’class second(first)’:

Pay ATTENTION to indentation!

#in.py
class first():
	n = 0
	def __init__(self, color=’red’):
		self.color = color
	def Hello1(self):
		print "Hello from first class!"
	def Color(self):
		print "My color from first class", self.color
class second(first):
	def Hello2(self):
		print "Hello from second class!"
		print self.n, "is my favorite number"
a0=first()
a0.Color()
print ’-------’
a1=first(’blue’)
a1.Hello1()
a1.Color()
print ’-------’
a2=second(’white’)
a2.Hello1()
a2.Hello2()
a2.Color()

6.1.7 __private

The Double underscore prefix is dealt with using ↓name mangling to effectively make it private within class or object.

6.1.8 The Kung Fu of Class

All classes in python are derived from a special top down ↓parent class called object that may or may not be ↓explicitly derived.

class KungFu(Object):

In Python a class that is derived from the ’superclass’ is called the ’subclass’. Let’s inherent from the parent class in the example below.

#kungfu.py
class KungFu(object):
	mystr=”the master”
	pass
class Master(KungFu):
	pass
teacher=Master.mystr
print teacher

Results:

The master

Now override attribute value in ↓subclass.

#kungfu1.py
class KungFu(object):
	mystr=”the master”
class Master(KungFu):
	mystr=”Student is not the master”
teacher=Master.mystr
print teacher

Results:

Student is not the master

Execute method from parent class inside subclass.

#kungfu2.py
class KungFu(object):
	mystr=”the master”
	def crane(self):
		print ”crane kick”
class Master(KungFu):
	mystr=”Student is not the master”
teacher=Master()
teacher.crane()

Results:

crane kick

Override parent class with sublcass.

#kungfu3.py
class KungFu(object):
	mystr=”the master”
	def crane(self):
		print ”crane kick”
class Master(KungFu):
	mystr=”Student is not the master”
	def crane(self,bstr):
		print ”must learn crane kick”
teacher=Master()
teacher.crane(1)

Results:

must learn crane kick

6.1.9 Iterate Over Unknown Objects

Time and again I have found myself working with large applications that are poorly documented. Below is a handy method to parse potentially unknown objects via subclass. Pretend ’class bar’ has a lot of methods (perhaps thousands of methods) and you want to generate a list for easy lookup. This is a great troubleshooting exercise to get a summary of methods contained within a class.

Pay ATTENTION to indentation!

#!/usr/bin/python
#unknown.py
class bar:
	def blah(self):
		print "cool"
	def strange(self):
		print "wow"
	def nice(self):
		print "very cool now"
	def bazinga(self):
		print “bazinga”
class foo(bar):
	def __iter__(self): # iterate unknown
		return iter(vars(bar)) # vars built-in attr
a=foo()
for i in a:
	print i

Results:

__module__
bazinga
blah
strange
__doc__
nice

As you venture further into OOP. Subclassing a parent class to change an attribute will occur frequently and eventually you will want to track your own methods or an existing method this is a brief example on how to look at your work from a different perspective.

6.1.10 ↓Multiple Inheritence

I’m not crazy about using multiple inheritance or super. Multiple inheritance should be avoid and replaced with design patterns and if you plan to use ’super()’ it’s usage should be consistent. In class hierarchy, super should be used everywhere or nowhere. Mixing super and classic call is extremely confusing and doesn’t make things explicit. Instead focus on customizing classes and leverage methods such as ’__getattr__’, ’__setattr__’ and ’__getattribute__’. Please do not type the following code below, it is only an example: Use the IDLE interpreter and type help(super)

>>>help(super)

class super(object)
| super(type, obj) -> bound super object; requires isinstance(obj, type)
| super(type) -> unbound super object
| super(type, type2) -> bound super object; requires issubclass(type2, type)
| Typical use to call a cooperative superclass method:
| class C(B):
| def meth(self, arg):
etc...

6.1.11 Summary

These are the basic terminologies of object-oriented programming and mastering these concepts will allow you to build and scale large applications.


To post a comment you need to login first.