My Python-oriented slides

Download Report

Transcript My Python-oriented slides

CSC 310 – Theory of Programming
Languages, Spring, 2009
Chapter 9: Data Abstraction and
Object Orientation
Review of Object-Oriented
Programming – Encapsulation
• A module encapsulates implementation code and
data, exposing abstract interfaces to client code
while hiding implementation details.
• Also called information hiding, this approach does
not necessarily entail using objects.
• C++ namespaces, Java packages, Python packages and
modules.
• It reduces conceptual load, provides fault
containment, and provides component
independence.
Interface Inheritance
• An interface defines operations and symbolic
constants that specify operation signatures
and semantics.
• C++ abstract class consisting of pure virtual functions
and constant definitions, Java interface, Python class
with method declarations that throw exceptions.
• Derived concrete classes implement the
operations of a base class interface while
hiding implementation details.
sequence_interface (ADT) –
sequence of string objects
cp ~parson/JavaLang/sequence_adt ~/JavaLang/sequence_adt
<<interface>>
sequence_interface
sequence_interface.java
insert(value : string, offset : integer) : boolean
remove(offset : integer) : boolean
get(offset : integer) : string
size() : integer
Concrete class sequence_arrayimpl
implements sequence_interface
<<interface>> sequence_interface
sequence_arrayimpl
insert(), remove()
get(), size()
private String [] array ;
private int count ;
actually used
// number of array elements
Class sequence_linkedlistimpl
implements sequence_interface
<<interface>> sequence_interface
sequence_linkedlistimpl
insert(), remove()
get(), size()
private static class listelement { // private local helper class
String content ; // string stored at this element
listelement next ; // next element, higher in number than this one
}
private listelement first ;
private int count ;
// number of linked list nodes actually used
Implementation Inheritance
• An abstract or concrete base class provides
fields, public methods and protected methods
used in common by alternative
implementations in derived classes.
• Protected fields and methods are accessible only to
derived classes. They are part of shared
implementation. They eliminate duplicate code.
• Public fields and methods are accessible to client code,
and methods can be redefined or extended by derived
classes.
Package sequence_aclass class
sequence_abstract_baseclass
<<interface>> sequence_interface
<<abstract>> sequence_abstract_baseclass
size() : int
protected int getRealOffset(int offset, boolean isinsert) : int
(helper method to convert an offset parameter to a real offset)
protected int count
sequence_arrayimpl sequence_linkedlistimpl sequence_arraylistimpl
Subtype Polymorphism
• Derived classes that implement a common interface
can take various forms.
• Each class can provide an implementation that is
extended, customized or optimized for some class of
client applications.
• Once object construction is complete, client access
occurs via a pointer or reference to a base class or
interface object.
• The concrete run-time objects accessed via such a
pointer or reference have many forms.
Module encapsulation in Python
• A package takes the form of a directory
containing one or more Python modules.
• The package name is a “.”-separated path
name below a directory on PYTHONPATH.
• A module is a Python source file within a
package directory with related data and code
definitions.
• Clients must import components of a module.
Python Packages
• Assuming $HOME/ProcLang is on my PYTHONPATH,
package mysort corresponds to directory
$HOME/ProcLang/mysort.
• File __init__.py contains a list of every module name
in the package in its __all__ variable.
• ~parson/ProcLang/mysort/__init__.py contains the
assignment __all__ = ["mysort"] for module mysort.py.
Most packages contain multiple modules.
• This list provides support for “from mysort import *”
from other modules. It tells Python what modules to
import.
Importing Python Modules
• Importing a module without importing explicit
symbols requires using the module name as a prefix.
• >>> import sys ; sys.exit(1)
• Importing distinct names restricts the import and
makes those name first class objects.
• from sys import exit ; exit(1)
• from sys import exit as byebye ; byebye(1)
• Importing “*” imports all modules in a package or all
symbols in a module.
• Python does not report symbol collisions from multiple modules. It
uses the most recent import.
Python Classes
• Classes are dynamic constructs in Python, like
everything else.
• There is no compiler check to ensure definition of
“abstract methods” in concrete derived classes
(there are no abstract methods) or method signature
compatibility between base and derived classes.
• Inherited symbol access is a series of dictionary
lookups from derived to base classes.
• All fields and methods are public. Naming
conventions document intended access limitations.
Classy Examples
>>> class baseclass(object):
... """ baseclass is an example """
... @staticmethod
... def statmethod():
…
print "statmethod in baseclass"
... def __init__(self, val):
...
self.value = val
... def f(self, newval):
...
oldval = self.value
...
self.value = newval
...
return oldval
>>> class d1(baseclass):
... @staticmethod
... def statmethod(): print
"statmethod in d1"
... def __init__(self, val):
...
return super(d1,
self).__init__(val)
>>> D1 = d1(3)
>>> D1.f(5)
3
>>> D1.f(7)
5
More Classy Examples
>>> class d2(baseclass):
... def f(self, newval):
...
oldval = self.value
...
self.value = newval + 10.0
...
return oldval
>>> D2 = d2(5)
>>> D2.f(1)
5
>>> D2.f(3)
11.0
>>> isinstance(D2, d2)
True
>>> isinstance(D2, baseclass)
True
>>> isinstance(D2, d1)
False
>>> issubclass(d1, baseclass)
True
>>> issubclass(d1, d1)
True
>>> issubclass(d1, d2)
False
No method name overloading
• Both the constructor method, called __init__, and
other methods within the class, must have unique
names. There is no name overloading in Python.
• Calls to superclass __init__ are explicit in explicit order. The class
determines construction order.
• You can supply default parameter values.
• Methods can test for argument types.
• Methods can use variable number of *positional and
**keyword arguments.
• There are no destructors in Python. The garbage collector invokes __del__(self) on
an object being recovered, but most classes do not redefine __del__.
Operator overloading and
extension of built-in types
• You can overload Python operators such as + by
defining special methods such as __add_ and
__radd__ -- see PY Chapter 3.
• You can extend built-in types.
>>> class coercive_int(int):
... def __init__(self, value):
...
super(coercive_int,self).__init__(self, value)
... def __add__(self, value):
...
print "Inside method __add__"
...
return int(self) + int(value)
... def __radd__(self, value):
...
print "Inside method __radd__"
...
return int(self) + int(value)
User-extended types in expressions
>>> ci = coercive_int(3)
>>> ci
3
>>> ci + 4.0
Inside method __add__
7
>>> int(ci) + 4.0
7.0
>>> coercive_int(ci) + 4.0
Inside method __add__
7
>>> 4.0 + ci
7.0
>>> "12345" + ci
Inside method __radd__
12348
>>> "12345" + 3
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: cannot concatenate 'str' and
'int' objects
Multiple Inheritance uses Mixins
• Each base class can be a fragment of a class
that refers to symbols defined in other
fragmentary or complete classes.
• Combining fragmentary classes via multiple
inheritance supplies their missing parts.
• Python’s SocketServer module has both UDPServer and
TCPServer classes, and threading and forking mixin
classes. You can define derived classes like this:
ThreadingTCPServer(ThreadingMixIn, TCPServer)
ForkingUDPServer(ForkingMixIn, UDPServer)
Mixin Inheritance
• Mixin inheritance requires application-specific names
for methods and possibly fields contributed by mixin
component classes.
• Multiple implementation inheritance of complete
base classes is also possible.
• Python walks a class’ inheritance graph in left-toright order, from most-to-least derived, backing up
before shared base classes, to search for symbols
and to resolve conflicts.
• Print CLASSNAME.__mro__ shows the class ordering.
Deciphering multiple inheritance
>>> class d11(d1): pass
>>> class d12(d1) : pass
>>> class d21(d2) : pass
>>> class d22(d2) : pass
>>> class multi(d11, d12, d21, d22): pass
>>> multi.__mro__
(<class '__main__.multi'>, <class '__main__.d11'>, <class
'__main__.d12'>, <clas
s '__main__.d1'>, <class '__main__.d21'>, <class '__main__.d22'>, <class
'__main
__.d2'>, <class '__main__.baseclass'>, <type 'object'>)
multi(d11, d12, d21, d22):
All method bindings are either
object-dynamic or class-static.
• The Python bytecode interpreter looks for field and
method symbols within class objects using the
__mro__ class ordering graph. All lookup is dynamic.
• There is nothing like a C++ non-virtual member
function that is bound statically by the compiler.
• @staticmethod-tagged methods require no object.
They can be invoked using a class name or an object
of that class as a prefix. Resolution of static methods
also uses __mro__ for an object prefix.
Python metaclasses (end of PY Ch. 7)
• Derive a class from type or class and define or
redefine the appropriate methods.
• This new type can create alternatives to
“class” for creating user-defined types.
• http://www.ibm.com/developerworks/linux/library/lpymeta.html
• http://www.onlamp.com/pub/a/python/2003/04/17/metacla
sses.html?page=1
• http://www.python.org/download/releases/2.2/descrintro/