232x Filetype PDF File size 0.23 MB Source: st.inf.tu-dresden.de
Object-oriented programming with Python
Anintroduction into OOP and design patterns with Python
MaxLeuthäuser
s7060241@mail.zih.tu-dresden.de
TUDresden
Abstract 1. TheBasics
Whileprogrammingitselfisarelatively young discipline, you may Asmentionedaboveyoushouldalreadybefamiliarwithbasicslike
finditsurprisingthatobject-orientedprogramming(OOPfromnow the following ones, so this is simply a small summary to repeat and
on)actuallygoesbackasfarasthe1960’s.Simula1 isconsideredto keep things in mind. Advanced users might skip this and continue
bethefirst object-oriented programming language. This paper tries reading the "Advanced language extensions" part or dive directly
to dive quickly into OOP with Python and give a small introduction into "Design Patterns with Python".
into important basics. Later we find more advanced techniques 1.1 Whatisanobject?
with design patterns. This paper assumes a minimal knowledge of
Python syntax. If you know how to create the basic data-types and Weare in the domain of programming - so an object is a concept.
call functions, but want to know more about objects, classes, design Calling elements of our programs objects is a metaphor - a useful
patterns and advanced built-in language extensions you may find way of thinking about them. In Python the basic elements of pro-
this helpful. gramming are things like strings, dictionaries, integers, functions,
6
and so on. They are all objects .
Introduction 1.2 Asmallreference to procedural programming
Using a procedural style of programming, programs are often split
OOPitself is a controversial paradigm, in fact it is not even clear into reusable "chunks" called functions and methods. The resulting
what a strict definition of OOP is. Actually some people think that code is easier to maintain. These chunks are callable at different
OOP has nearly had its days, and we need to find the post OOP places in your program so improving one method or function will
paradigm2. So it is not very surprising that others like Paul Gra- enhancetheperformanceonseveralplaces. Anotherimportantfact
ham3 think it was never necessary in the first place. But in general to keep in mind when talking about OOP comes from procedural
OOPisbasicallyastandard.Mostlinesofcodenowadaysarewrit- programmingaswell. It maintains a strict separation between your
4 code and your data. You have variables, which contain your data,
ten with object-oriented (and semi object orientated) languages . It
is not the task of this paper to underline all the advantages of Python andprocedures.Youpassyourvariablestoyourprocedures-which
now, but some basic facts are important. The whole design philos- act on themandperhapsmodifythem.Ifafunctionwantstomodify
ophy of Python encourages a clean programming style. Its basic the content of a variable by passing it to another function it needs
datatypes and system of namespaces makes it easier to write ele- access to both the variable and the function it’s calling. If you are
gant, modular code5. These factors and the unique block structure performing complex operations this could be lots of variables and
byindentation rules are very helpful for reading and understanding lots of functions.
code. Actually the basic principles of object-oriented programming 1.3 Talking about python basics
are relatively easy to learn. Like other aspects of Python they are
nicely implemented and well thought out. TraditionallyessentialelementsofOOPareencapsulationandmes-
The remaining part of this paper is organized as follows: The sagepassing.ThePythonequivalentsarenamespacesandmethods.
next two sections introduce the object orientated programming Pythondoesnotsubscribetoprotectingthecodefromtheprogram-
paradigm and its basics - especially with Python. After this some mer, like some of the more BSD languages. Python does encapsu-
importantfactswithinheritanceandadditionallanguageextensions late objects as a single namespace but it is a translucent encapsu-
are discussed. This is concluded with some simple measurements lation. The following introductions are visualized using the string
and some broader observations on using design patterns in Python. object as an example.
This paper is full of examples written in Python and C++ and/or 1.3.1 Using objects
Java. Feel free to compile them, they may help to understand what
wasmeantinthetext. Asalready mentioned above it turns out that lots of operations are
commontoobjects of the same type. For example most languages
have built-in ways to create a lowercase version of a string. Actu-
1 http://en.wikipedia.org/wiki/Simula ally there are a lot of standard operations to interact with strings.
2 http://www.americanscientist.org/Issues/Comsci03/03-03Hayes.html Building an uppercase version, splitting and concatenating, and so
3 http://www.paulgraham.com/noop.html on. In an object-oriented language we can build these in as prop-
4 erties of the string object. In Python we call these methods. Every
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
5 Python’s system of modules and packages as well - these are related to 6Like Smalltalk - which is sometimes spoken of as the archetypal object-
namespaces, and are the envy of other languages. oriented language.
1
string object has a standard set of methods. This is true for all kinds Last thing in this section is making use of some simple dictionary
of objects in Python. Consider the following example (code taken methods.
from [1]): a_dict = {
original_string = ’ some text ’ ’ key ’ : ’ value ’ ,
# remove leading and trailing whitespace ’ key2 ’ : ’ value2 ’
string1 = original_string . strip () }
a_dict_2 = a_dict .copy()
# make uppercase print a_dict == a_dict_2
string2 = string1 . upper () True
print string2 a_dict . clear ()
> SOME TEXT print a_dict
{}
# make lowercase print a_dict . clear
string2 . lower () == string1 True x0012E540>
print type( a_dict . clear )
Python uses the dot syntax (like Java or C#) to access attributes
of objects. The statement string2.lower() means call the lower The clear method of a_dict was used by calling a_dict.clear().
method of the object string2. This method returns a new string When we printed clear, instead of calling it, we can see that it is
- the result of calling the method. So every string is actually a just another object. It is a method object of the appropriate type.
string object - and has all the methods of a string object. In Python
terminology we say that all strings are of the string type. In the 1.3.3 Using functions as objects
object model the functions (methods) and other attributes that are Todemonstratethatfunctionscanbeobjectsconsiderthefollowing
associated with a particular kind of object become part of the code. You may have written something like this before in some
object. The data and the functions for dealing with it are no longer other language:
separate - but are bound together in one object.
1.3.2 Creating objects i f value == ’one’:
In Python there is a blueprint string object called the string type. Its # do something
actual name is str. It has all the methods and properties associated function1 ()
with the string as already described above. Each single time a elif value == ’two’:
new string is created, the blueprint is used to create a new object # do something else
with all the properties of the blueprint. All the built-in datatypes function2 ()
have their own blueprint, e.g. the integer (int), the float (float), elif value == ’three ’:
booleans (bool), lists (list), dictionaries (dict), and some more. For # do something else
this datatypes it is possible to use the standard Python syntax to function3 ()
create them or we can use the blueprint itself - the type. Other languages (e.g. Java ) have a construct called switch that
# create a dictionary the normal way makes writing code like that a bit easier. In Python we can achieve
a_dict = { thesamething(inlesslinesofcode)usingadictionaryoffunctions.
’ key ’ : ’ value ’ , Asanexample, suppose we have three functions. You want to call
’ key2 ’ : ’ value2 ’ one of the functions, depending on the value in a variable called
} choice.
# use ’dict ’ to create one def function1 () :
l i s t _ o f _ t u p l e s = [( ’key ’ , ’value ’) , print ’You chose one. ’
( ’ key2 ’ , ’ value2 ’) ] def function2 () :
a_dict_2 = dict ( list_of_tuples ) print ’You chose two. ’
# def function3 () :
print a_dict == a_dict_2 print ’You chose three . ’
True
print type( a_dict ) # switch is our dictionary of functions
switch = {
print type(a_dict_2) ’ one ’ : function1 ,
’two’: function2 ,
a_dict_2 was created by passing a list of tuples to dict. Very ’ t h r e e ’ : function3 ,
basic, but it illustrates that new objects are created from blueprints. }
These objects have all the methods defined in the blueprint. The # choice can either be ’one ’, ’two ’, or ’
new object is called an instance and the process of creating it is t h r e e ’
called instantiation (meaning creating an instance). For the built- choice = raw_input( ’Enter one , two , or three
in datatypes the blueprint is known as the type of the object. You
7 : ’ )
can test the type of an object by using the built-in function type.
7 Actually type is not a function - it is a type. Exactly the type of types # call one of the functions
(type(type) is type). It is used as function here. try :
2
r e s u l t = switch[choice] instance is a reference to our new object. We access the printargs
except KeyError: method of the instance object using instance.printargs. In order to
print ’I did not understand your choice . access object attributes from within the __init__ method we need
’ a reference to the object within the method of the object itself.
else : Whenever a method is called, a reference to the main object is
r e s u l t ( ) passed as the first argument. By convention you always call this
first argument to your methods self.
Thepointofinterestis:result=switch[choice].Theswitch[choice]
returns one of our function objects (or raises a KeyError). Finally 1.5 Conclusions for this section
result() is called which does the trick. So what are the advantages of using OOP and what is so useful
1.4 Makinguseofuserdefinedclasses using objects?
Much more interesting is that we can create our own blueprints. Objects combine data and the methods used to work with the
These are called classes. We can define our own class of object - data. So it is possible to wrap complex processes - but present a
andfromthiscreate as many instances of this class as we want. All simple interface to them. How these processes are done inside the
the instances will be different - depending on what data they are object becomes a mere implementation detail. Anyone using the
given when they are created. They will all have the methods (and object only needs to know about the methods and attributes. This is
other properties) from the blueprint. Take a look at the following the real principle of encapsulation. Other parts of your application
simple example. We define our own class using the class keyword. (or even other programmers) can use your classes and their public
Methods are defined like functions - using the def keyword. They methods - but you can update the object without breaking the
are indented to show that they are inside the class. interface they use.
Youcanalso pass around objects instead of data. This is one of
class OurClass( object ) : the most useful aspects of OOP. Once you have a reference to the
def __init__ ( self , arg1 , arg2) : object you can access any of the attributes of the object. If you need
self . arg1 = arg1 to perform a complex group of operations as part of a program you
self . arg2 = arg2 could probably implement it with procedures and variables. You
might either need to use several global variables for storing states
def printargs ( self ) : (which are slower to access than local variables and not good if
print self . arg1 a module needs to be reusable within your application) - or your
print self . arg2 procedures might need to pass around a lot of variables.
If you implement a single class that has many attributes repre-
Nowitiseasytocreate an own instance: senting the state of your application, you only need to pass around
a reference to that object. Any part of your code that has access to
i n s t a n c e = OurClass( ’arg1 ’ , ’arg2 ’) the object can also access its attributes.
print type( instance ) Themainadvantageofobjectsisthattheyareausefulmetaphor.
It fits in with the way we think. In real life objects have certain
i n s t a n c e . p r i n t a r g s ( ) properties and interact with each other. The more our programming
arg1 language fits in with our way of thinking, the easier it is to use it to
arg2 think creatively [1].
To go back to Python itself the "everything is an object" men-
The arguments arg1 and arg2 are passed to the constructor as tality should be mentioned.
arguments. Later they are printed using the method printargs(). To
get a deeper understanding what happened here we need to know 2. Everything is an object
moreabouttheconstructor and the things which are related to this.
1.4.1 The__init__ method As you now know already from above everything in Python is
an object, and almost everything has attributes and methods. All
The__init__ method (init for initialise) is called when the object is functions have a built-in attribute __doc__, which returns the doc
instantiated. Instantiation is done by (effectively) calling the class. string (short usage documentation of the function) which is defined
It is also known a the constructor as mentioned above. This is in the function’s source code. The sys module is an object having
very similar to Java where the constructor has always the name as an attribute called path. And so forth.
the class itself followed by the list of the arguments surrounded InPython,thedefinitionfor"object"isquiteweak;someobjects
by brackets. The only thing leftover now is the confusing self haveneitherattributes nor methods and not all objects are subclass-
parameter. able. But everything is an object in the sense that it can be assigned
to a variable or passed as an argument to a function.
1.4.2 Understanding the self parameter
The arguments accepted by the __init__ method (known as the 2.1 First class functions
methodsignature) are: Simplyspokenfirstclassfunctionsallowrun-timecreationoffunc-
tions from functions. It do not have to be members of some class.
def __init__ ( self , arg1 , arg2) : 8
Theexact definition is something like this : In computer science, a
This is a little bit confusing. When we initiate the object we programming language is said to support first-class functions (also
actually pass only two arguments: called function literals, function types) if it treats functions as first-
class objects. Specifically, this means that the language supports
i n s t a n c e = OurClass( ’arg1 ’ , ’arg2 ’) constructing new functions during the execution of a program, stor-
ing them in data structures, passing them as arguments to other
Sowheredoestheextraargumentcomesfrom?Whenweaccess
attributes of an object we do it by name (or by reference). Here 8http://en.wikipedia.org/wiki/First-class_function
3
functions, and returning them as the values of other functions. This as follows: the corresponding class attribute is searched, descend-
conceptdoesnotcoveranymeansexternaltothelanguageandpro- ing down the chain of base classes if necessary, and the method
gram (meta programming), such as invoking a compiler or an eval reference is valid if this yields a function object.
function to create a new function. Derived classes may override methods of their base classes.
Because methods have no special privileges when calling other
2.2 Metaprogrammingwithon-the-flymethodpatching methods of the same object, a method of a base class that calls
On-the-fly method patching, also known as bind unbound methods another method defined in the same base class may end up calling
is some kind of attaching any method (which is actually a method a method of a derived class that overrides it.
object) at a specific class in the way of meta programming. At An overriding method in a derived class may in fact want to
this part I do not want to make use of some fancy explanation or extend rather than simply replace the base class method of the
definition9. A simple example should visualize the functionality: same name. There is a simple way to call the base class method
Wesimplycreate a class directly: just call BaseClassName.methodname(self, arguments).
10
This is occasionally useful to clients as well .
class A: Pythonhastwobuilt-infunctionsthatworkwithinheritance[2]:
b = 3 • Useisinstance() to check an instance’s type: isinstance(obj, int)
and create an instance. will be True only if obj.__class__ is int or some class derived
from int.
a = A() • Use issubclass() to check class inheritance: issubclass(bool,
print a.b int) is True since bool is a subclass of int. However, issub-
3 class(unicode, str) is False since unicode is not a subclass of
Nowwecreateafirst-class function. str (they only share a common ancestor, basestring).
def f( self , a) : 3.2 Small insertion - private variables
return a + self .b "Private" instance variables that cannot be accessed except from in-
sideanobjectdonotexistinPython.However,thereisaconvention
Finally we install that function in the class. that is followed by most Python code: a name prefixed with an un-
A. fred = f derscore (e.g. _spam) should be treated as a non-public part of the
API(whetheritisafunction,amethodoradatamember).Itshould
Socalling that function on the instance of A() does the trick. beconsideredanimplementationdetailandsubjecttochangewith-
out notice [2].
print a. fred (4) Sincethereisavaliduse-caseforclass-privatemembers(namely
7 to avoid name clashes of names with names defined by subclasses),
there is limited support for such a mechanism, called name man-
gling 11. Any identifier of the form __spam (at least two leading
3. Inheritance underscores, at most one trailing underscore) is textually replaced
with_classname__spam,whereclassnameisthecurrentclassname
3.1 Single inheritance with leading underscore(s) stripped. This mangling is done without
Of course Python supports inheritance and even a limited form of regard to the syntactic position of the identifier, as long as it occurs
multiple inheritance as well. The syntax looks basically like this: within the definition of a class.
Note that the mangling rules are designed mostly to avoid acci-
class DerivedClassName(BaseClassName): dents;itstill is possible to access or modify a variable that is consid-
ered private. This can even be useful in special circumstances, such
. . . as in the debugger. These rules are comparable to the Java keyword
private but are completely voluntarily and are the responsibility of
of the programmer.
The name BaseClassName must be defined in a scope contain-
ing the derived class definition. In place of a base class name, other 3.3 Multiple Inheritance
arbitrary expressions are also allowed. This can be useful, for ex- Aclass definition with multiple base classes looks like this:
ample, when the base class is defined in another module:
class DerivedClassName(modname.BaseClassName class DerivedClassName(Base1 , Base2 , Base3) :
) :
. . .
Execution of a derived class definition is actually the same as
no reviews yet
Please Login to review.