Professional Documents
Culture Documents
Python Oo
Python Oo
Purdue University
Purdue University 1
The Reason for This Material at the Outset
A large majority of people who play with deep learning algorithms operate in the
zombie mode — meaning that they simply run canned programs downloaded
from the internet with the expectation that a combination of the downloaded
software and their own dataset would lead to results that would somehow pave
their way to fame and fortune. This, unfortunately, is no way for a student to
prepare himself or herself for the future.
The goal of our deep learning class is to help you become more genuine in how
you utilize your deep learning skills.
Regarding this lecture, in what follows, I’ll start with the main concepts of OO
programming in general and then devote the rest of the material to Python OO.
Purdue University 2
Outline
Outline
Purdue University 4
Some Examples of PyTorch Syntax
The statement in the third line appears to indicate that we are using
xform as a function which is being returned by the statement in the
second line. Does that mean functions in Python return functions?
To fully understand what’s going on here you have to know what’s meant
by an object being callable. Python makes a distinction between function
objects and callables. While all function objects are callables, not all
callables are function objects.
Purdue University 5
Some Examples of PyTorch Syntax
But why are we making the call super(EncoderRNN, self). init () and
supplying the name of the subclass again to this method? To understand
this syntax, you have to know how you can ask a method to get part of
the work done by a method defined for one of its superclasses. How that
works is different for a single-inheritance class hierarchy and for a
multiple-inheritance class hierarchy.
Purdue University 6
Some Examples of PyTorch Syntax
train_data_loader = torch.utils.data.DataLoader(
training_data, batch_size=self.batch_size,shuffle=True, num_workers=2)
or calls like
for data in train_data_loader:
inputs,labels = data
...
outputs = model(inputs)
...
Purdue University 9
The Main OO Concepts
Outline
Purdue University 10
The Main OO Concepts
Purdue University 11
The Main OO Concepts
An instance constructed from a class will have specific values for the
attributes.
Purdue University 12
The Main OO Concepts
Purdue University 13
The Main OO Concepts
Encapsulation
A client should only access those data attributes and invoke those
methods that are in the public interface.
Purdue University 14
The Main OO Concepts
Purdue University 15
The Main OO Concepts
Polymorphism (contd.)
Purdue University 16
The Main OO Concepts
All of the public methods and attributes defined for the root class
would constitute the public interface of the class hierarchy and each
class in the hierarchy would be free to provide its own implementation
for the methods declared in the root class.
Purdue University 17
Pre-Defined and Programmer-Supplied Attributes
Outline
Purdue University 18
Pre-Defined and Programmer-Supplied Attributes
Purdue University 19
Pre-Defined and Programmer-Supplied Attributes
Outline
Purdue University 22
Function Objects vs. Callables
On the other hand, a callable is any object that can be called like a
function.
Purdue University 23
Function Objects vs. Callables
You will see objects that may be called with or without the ‘()’
operator and, when they are called with ‘()’, there may or may not
exist any arguments inside the parentheses.
For a class X with method foo, calling just X.foo returns a result
different from what is returned by X.foo(). The former returns the
method object itself that X.foo stands for and the latter will cause
execution of the function object associated with the method call.
Purdue University 24
Function Objects vs. Callables
import random
random.seed(0)
#---------------------------- class X -------------------------------
class X:
def __init__( self, arr ) :
self.arr = arr
def get_num(self, i):
return self.arr[i]
def __call__(self):
return self.arr
#------------------------ end of class definition ---------------------
xobj = X( random.sample(range(1,10), 5) )
print(xobj.get_num(2)) # 1
print(xobj()) # [7, 9, 1, 3, 5]
If you execute this code, you will see the output shown in the commented
out portions of the last two lines.
In the last line of the code, note how we are calling the function call
operator ’()’ on the instance constructed from the class X.
Purdue University 25
Function Objects vs. Callables
import random
random.seed(0)
#---------------------------- class X ---------------------------
class X:
def __init__( self, arr ) :
self.arr = arr
def get_num(self, i):
return self.arr[i]
# def __call__(self):
# return self.arr
#------------------------ end of class definition ----------------
xobj = X( random.sample(range(1,10), 5) )
print(xobj.get_num(2)) # 1
print(xobj()) # Traceback (most recent call last)
# File "UsingCall2.py", line 15, in <module>
# print(xobj())
# TypeError: ’X’ object is not callable
Purdue University 26
Defining a Class in Python
Outline
Purdue University 27
Defining a Class in Python
I’ll start with a very simple example of a class to make the reader
familiar with the pre-defined init () method whose role is to
initialize the instance returned by a call to the constructor.
Purdue University 28
Defining a Class in Python
#test code:
a_person = Person( "Zaphod", 114 )
print(a_person.name) # Zaphod
print(a_person.age) # 114
Purdue University 29
Defining a Class in Python
Being an object in its own right, every Python class comes equipped
with the following pre-defined attributes:
Purdue University 30
Defining a Class in Python
Since every class instance is also an object in its own right, it also
comes equipped with certain pre-defined attributes. We will be
particularly interested in the following two:
class : string name of the class from which the instance was
constructed
dict : dictionary whose keys are the names of the instance
variables
Purdue University 31
Defining a Class in Python
dir( MyClass )
that returns a list of all the attribute names, for variables and for
methods, for the class (both directly defined for the class and
inherited from a class’s superclasses).
Purdue University 32
Defining a Class in Python
#test code:
a_person = Person("Zaphod",114)
print(a_person.name) # Zaphod
print(a_person.age) # 114
# class attributes:
print(Person.__name__) # Person
print(Person.__doc__) # A very simple class
print(Person.__module__) # main
print(Person.__bases__) # ()
print(Person.__dict__) # {‘__module__’ : ‘__main__’, ‘__doc__’ : ‘A very simp..’,
# ‘__init__’:<function __init..’,
# instance attributes:
print(a_person.__class__) # __main__.Person
print(a_person.__dict__ ) # {‘age’:114, ‘name’:’Zaphod’}
Purdue University 33
Defining a Class in Python
class MyClass :
‘optional documentation string’
class_var1
class_var2 = var2
...
...
Purdue University 34
Defining a Class in Python
Regarding the syntax shown on the previous slide, note the class
variables class var1 and class var2. Such variables exist on a
per-class basis, meaning that they are static.
If you do not provide a class with its own init (), the system will
provide the class with a default init (). You override the default
definition by providing your own implementation for init ().
The syntax for a user-defined method for a class is the same as for
stand-alone Python functions, except for the special significance
accorded the first parameter, typically named self. It is meant to be
bound to a reference to the instance on which the method is invoked.
Purdue University 36
Defining a Class in Python
All classes are subclassed, either directly or indirectly from the root
class object.
We can also examine the attribute list available for the object class
by printing out the contents of its dict attribute by
print( object.__dict__ )
This will print out both the attribute names and their bindings.
Purdue University 37
How Python Creates an Instance: new() vs. init()
Outline
Purdue University 38
How Python Creates an Instance: new() vs. init()
STEP 1:
Purdue University 39
How Python Creates an Instance: new() vs. init()
If a class does not provide its own definition for new (), a search is
conducted for this method in the parent classes of the class.
STEP 2:
Purdue University 40
How Python Creates an Instance: new() vs. init()
Purdue University 41
How Python Creates an Instance: new() vs. init()
In the script on the next slide, also note that the namespace
dictionary xobj. dict created at runtime for the instance xobj is
empty — for obvious reasons.
Purdue University 42
How Python Creates an Instance: new() vs. init()
Purdue University 43
How Python Creates an Instance: new() vs. init()
Purdue University 44
Defining Methods
Outline
Purdue University 45
Defining Methods
A method defined for a class must have special syntax that reserves
the first parameter for the object on which the method is invoked.
This parameter is typically named self for instance methods, but
could be any legal Python identifier.
In the script shown on the next slide, when we invoke the constructor
using the syntax
xobj = X( 10 )
the parameter self in the call to init () is set implicitly to the
instance under construction and the parameter nn to the value 10.
A method may call any other method of a class, but such a call must
always use class-qualified syntax, as shown by the definition of bar()
on the next slide.
Purdue University 46
Defining Methods
In the definition shown below, one would think that a function like baz() in
the script below could be called using the syntax X.baz(), but that does not
work. (We will see later how to define a class method in Python).
#---------- class X ------------
class X:
def __init__(self, nn): # the param ’self’ is bound to the instance
self.n = nn
def getn(self): # instance method
return self.n
def foo(self,arg1,arg2,arg3=1000): # instance method
self.n = arg1 + arg2 + arg3
def bar( self ): # instance method
self.foo( 7, 8, 9 )
def baz(): # this is NOT how you define a class method
pass
#--- End of Class Definition ----
xobj = X(10)
print( xobj.getn() ) # 10
xobj.foo(20,30)
print( xobj.getn() ) # 1050
xobj.bar()
print( xobj.getn() ) # 24
# X.baz() # ERROR
Purdue University 47
Defining Methods
In the script shown on the next slide, the important thing to note is
that is that the assignment to foo gives X an attribute that is a
function object. As shown, this object can then serve as an instance
method.
Purdue University 48
Defining Methods
xobj = X(10)
print( xobj.getn() ) # 10
xobj.foo( 20, 30 )
print( xobj.getn() ) # 1050
Purdue University 49
Defining Methods
class X:
def foo(self, arg1, arg2):
implemention_of_foo
rest_of_class_X
the compiler will introduce the name foo as a key in the namespace
dictionary for class X. The value entered for this key will be the
function object corresponding to the body of the method definition.
Purdue University 50
Defining Methods
Since all the method names are stored as keys in the namespace
dictionary and since the dictionary keys must be unique, this implies
that there can exist only one function object for a given method
name.
If after seeing the code snippet shown on the previous slide, the
compiler saw another definition for a method named for the same
class, then regardless of the parameter structure of the function,
the new function object will replace the old for the value entry for the
method name. This is unlike what happens in C++ and Java where
function overloading plays an important role.
Purdue University 51
Defining Methods
We just talked about how there can only be one method of a given
name in a class — regardless of the number of arguments taken by
the method definitions.
As a more general case of the same property, a class can have only
one attribute of a given name.
Purdue University 52
Defining Methods
And each time a variable whose referent object either goes out of
scope or is changed, the reference count associated with the object is
decreased by one. When the reference count associated with an
object goes to zero, it becomes a candidate for garbage collection.
Purdue University 53
Defining Methods
A Python class and a Python instance object are so open that they
can be modified after the objects are brought into existence.
Purdue University 54
Defining Methods
Purdue University 55
Defining Methods
robot1 = Robot("Zaphod")
print( robot1.get_idNum() ) # 1
robot2 = Robot("Trillian")
print( robot2.get_idNum() ) # 2
robot3 = Robot("Betelgeuse")
print( robot3.get_idNum() ) # 3
Purdue University 56
Defining Methods
Static Methods
Purdue University 57
Creating a Class Hierarchy
Outline
Purdue University 58
Creating a Class Hierarchy
In the next couple of slides, we will first consider the case of single
inheritance, that is, when each child class has a single parent class.
Purdue University 59
Creating a Class Hierarchy
The next two slides show a single inheritance hierarchy, with Employee
as the base class and the Manager as the derived class.
We want both the promote() and the myprint() methods of the derived
class to call on the method of the same names in the base class to do
a part of the job.
Purdue University 60
Creating a Class Hierarchy
def myprint(self):
print( self.name, "%s" % self.position, end=" ")
def promote(self): ## this promote() calls parent’s promote() for part of the work
if self.position == ’executive’:
print( "not possible" )
return
Employee.promote( self ) ## (A)
def myprint(self): ## this print() calls parent’s print() for part of the work
Employee.myprint(self) ## (B)
print( self.dept )
Purdue University 61
Creating a Class Hierarchy
Purdue University 62
Creating a Class Hierarchy
Purdue University 63
Creating a Class Hierarchy
def promote(self):
if self.position == ’executive’:
print( "not possible" )
return
super(Manager, self).promote() ## (A)
def myprint(self):
super(Manager, self).myprint() ## (B)
print( self.dept )
Purdue University 64
Creating a Class Hierarchy
The point of this slide is to emphasize what you might have noticed
already in the Employee-Manager class hierarchy: The first thing that the
constructor of a derived class must do is to call on the constructor of
the base class for the initializations that are in the latter’s init ().
In the code shown on the next slide, this call is made in line (A). As
you can see, the derived class is calling init () directly on the name
of the base class.
Purdue University 65
Creating a Class Hierarchy
Purdue University 66
Creating a Class Hierarchy
super(Manager, self).__init__(nam,pos)
The call to super() MUST mention the name of the derived class in
which super() is called.
Purdue University 67
Creating a Class Hierarchy
Purdue University 68
Creating a Class Hierarchy
Shown on the next slide is the same hierarchy that you saw on the
previous slide, but with the following new-style syntax for the call to
super() in line (A):
super().__init__(nam, pos)
Purdue University 69
Creating a Class Hierarchy
def promote(self):
if self.position == ’executive’:
print( "not possible" )
return
super(Manager, self).promote()
def myprint(self):
super(Manager, self).myprint()
print( self.dept )
#------------------ Test Code --------------------
emp = Employee("Orpheus", "staff")
emp.myprint() # Orpheus staff
print("\n")
emp.promote()
print( emp.position ) # manager
emp.myprint() # Orpheus manager
print()
man = Manager("Zaphod", "manager", "sales")
man.myprint() # Zaphod manager sales
man.promote()
print("\n")
print( man.position ) # executive
print(isinstance(man, Employee)) # True
print(isinstance(emp, Manager)) # False
print(isinstance(man, object)) # True
print(isinstance(emp, object)) # True
Purdue University 70
Multiple-Inheritance Class Hierarchies
Outline
Purdue University 71
Multiple-Inheritance Class Hierarchies
class B( A ):
def __init__(self):
print("called B’s init")
super().__init__()
class C( A ):
def __init__(self):
print("called C’s init")
super().__init__()
class D(B,C):
def __init__(self):
print("called D’s init")
super().__init__()
print(D.__mro__)
# (<class ’__main__.D’>, <class ’__main__.B’>, <class ’__main__.C’>, <class ’__main__.A’>, <t
Purdue University 73
Multiple-Inheritance Class Hierarchies
Purdue University 75
Multiple-Inheritance Class Hierarchies
The example shown on the next slide is basically the same as what
was shown in the previous slide: A GOOD-practice scenario in which
the original programmer of the ABC hierarchy has used the new-style
super() to call the parent class’s init () in the init () for all the
derived classes.
The only difference from the previous example is that the calls like
super(B,self).__init__()
Purdue University 77
Multiple-Inheritance Class Hierarchies
Purdue University 78
Multiple-Inheritance Class Hierarchies
Outline
Purdue University 80
Making a Class Instance Iterable
A class instance is iterable if you can loop over the data stored in the
instance. The data may be stored in the different attributes and in
ways not directly accessible by, say, array like indexing.
Commonly, the iterator defined for a class will itself be a class that
provides implementation for a method named next in Python 3 and
next in Python 2.
Purdue University 81
Making a Class Instance Iterable
class Xiterator:
def __init__(self, xobj):
self.items = xobj.arr
self.index = -1
def __iter__(self):
return self
def __next__(self):
self.index += 1
if self.index < len(self.items):
return self.items[self.index]
else:
raise StopIteration
next = __next__
#------------------------ end of class definition ---------------------
xobj = X( random.sample(range(1,10), 5) )
print(xobj.get_num(2)) # 1
print(xobj()) # [7, 9, 1, 3, 5] because xobj is callable
for item in xobj:
print(item, end=" ") # 7 9 1 3 5 because xobj is iterable
## Using the built-in iter() to construct a new instance of the iterator over the same instance of X:
it = iter(xobj) # iter() is a built-in function that calls __iter__()
print(it.next()) # 7
print(it.next()) # 9
Purdue University 83