Advanced Computer Programming Classes and Data Abstractions Sinan
Advanced Computer Programming Classes and Data Abstractions Sinan AYDIN
Object-oriented programming (OOP) Classes and Data Abstractions
Object-oriented programming (OOP) Classes and Data Abstractions Object-oriented programming (OOP) encapsulates (i. e. , wraps) data (attributes) and functions (behaviors) into components called classes. A class is like a blueprint. Using a blueprint, a builder can build a house. Using a class, a programmer can create an object (also called an instance). One blueprint can be reused many times to make many houses. One class can be reused many times to make many objects of the same class. Object-oriented programmers concentrate on creating their own user-defined types, called classes. Classes are also referred to as programmer-defined types. Each class contains data and the set of functions that manipulate the data. The data components of a class are called attributes (or data members). The functional components of a class are called methods (or member functions, in other objectoriented languages).
Implementing a Time Abstract Data Type with a Classes and Data Abstractions Classes simplify programming # Simple definition of class Time: """Time abstract data type (ADT) definition""" def __init__(self): """Initializes hour, minute and second to zero""" self. hour = 0 # 0 -23 self. minute = 0 # 0 -59 self. second = 0 # 0 -59 def print. Military(self): """Prints object of class Time in military format""" print("%. 2 d: %. 2 d" % (self. hour, self. minute, self. second )) def print. Standard( self ): """ Prints object of class Time in standard format""" standard. Time = "" if self. hour == 0 or self. hour == 12: standard. Time += "12: " else: standard. Time += "%d: " % (self. hour % 12) standard. Time += "%. 2 d: %. 2 d" % (self. minute, self. second) if self. hour < 12: standard. Time += " AM" else: standard. Time += " PM" print (standard. Time) t 1=Time() print(t 1. __doc__) t 1. print. Military() t 1. print. Standard() t 1. hour=9 t 1. minute=15 t 1. second=59 t 1. print. Military() print (Class. Name. __doc__) special method __init__: the constructor method of the class.
Special Attributes t 1=Time() t 1. print. Military() t 1. print. Standard() t 1. hour=9 t 1. minute=15 t 1. second=59 t 1. print. Military() print(t 1. __dict__) print(t 1. __doc__) print(t 1. __class__) Classes and Data Abstractions {'hour': 9, 'minute': 15, 'second': 59} Time abstract data type (ADT) definition <class '__main__. Time'>
Controlling Access to Attributes class Time 2: """Time abstract data type (ADT) definition""" def __init__(self): """Initializes hour, minute and second to zero""" self. hour = 0 # 0 -23 self. minute = 0 # 0 -59 self. second = 0 # 0 -59 def set. Time(self, hour, minute, second): """Set values of hour, minute, and second""" self. set. Hour(hour) self. set. Minute(minute) self. set. Second(second) def set. Hour(self, hour): """Set hour value""" if 0 <= hour < 24: self. _hour = hour else: raise Value. Error("Invalid hour value: %d" % hour) def set. Minute(self, minute): """Set minute value""" if 0 <= minute < 60: self. _minute = minute else: raise Value. Error("Invalid minute value: %d" % minute) def set. Second(self, second): """Set second value""" if 0 <= second < 60: self. _second = second else: raise Value. Error("Invalid second value: %d" % second) def get. Hour(self): """Get hour value""" return self. _hour def get. Minute(self): """Get minute value""" return self. _minute def get. Second(self): """Get second value""" return self. _second def print. Military(self): """Prints object of class Time in military format""" print("%. 2 d: %. 2 d" % (self. hour, self. minute, self. second )) def print. Standard( self ): """ Prints object of class Time in standard format""" standard. Time = "" if self. hour == 0 or self. hour == 12: standard. Time += "12: " else: standard. Time += "%d: " % (self. hour % 12) standard. Time += "%. 2 d: %. 2 d" % (self. minute, self. second) if self. hour < 12: standard. Time += " AM" else: standard. Time += " PM" print (standard. Time) t 2=Time 2() t 2. set. Time(9, 25, 35) t 2. print. Military() t 2. print. Standard() Classes and Data Abstractions
Private Attributes and Destructors class Private. Class: """Class that contains public and private data""" def __init__(self): """"Private class, contains public and private data members""" self. _public. Data = "public" # public data member self. __private. Data = "private" # private data membe def __del__(self): print("destructor") private = Private. Class() print (private. _public. Data) print (private. _Private. Class__private. Data) private. __del__() print (private. _public. Data) Classes and Data Abstractions
Using Default Arguments With Constructors def __init__( self, hour = 0, minute = 0, second = 0 ): time 1 = Time() # all default 13 time 2 = Time( 2 ) # minute, second default 14 time 3 = Time( 21, 34 ) # second default 15 time 4 = Time( 12, 25, 42 ) # all specified Classes and Data Abstractions
Class Attributes Classes and Data Abstractions class Employee: """Represents an employee""" count = 0 # class attribute def __init__(self, first, last): """Initializes first. Name, last. Name and increments count""" self. first. Name = first self. last. Name = last Employee. count += 1 # increment class attribute print ("Employee constructor for %s, %s" % ( self. last. Name, self. first. Name )) def __del__( self ): """Decrements count and prints message """ Employee. count -= 1 # decrement class attribute print ("Employee destructor for %s, %s" % ( self. last. Name, self. first. Name )) print ("Number of employees before instantiation is" , Employee. count) # create two Employee objects employee 1 = Employee( "Susan", "Baker" ) employee 2 = Employee( "Robert", "Jones" ) employee 3 = employee 1 print ("Number of employees after instantiation is" , employee 1. count) # explicitly delete employee objects by removing references del employee 1 del employee 2 del employee 3 print ("Number of employees after deletion is" , Employee. count) Number of employees before instantiation is 0 Employee constructor for Baker, Susan Employee constructor for Jones, Robert Number of employees after instantiation is 2 Employee destructor for Baker, Susan Employee destructor for Jones, Robert Number of employees after deletion is 0 Employee destructor for Baker, Susan
Composition: Object References as Members of Classes and Data Abstractions Until now, we have defined classes whose objects have attributes of basic types. Sometimes, a programmer needs objects whose attributes are themselves references to objects of other classes. For example, an object of class Alarm. Clock needs to know when it is supposed to sound its alarm, so why not include an object of class Time as a member of the object of class Alarm. Clock? Such a capability is called composition. class Date: """Class that represents dates""" # class attribute lists number of days in each month days. Per. Month = [ 0, 31, 28, 31, 30, 31] def __init__(self, month, day, year): """Constructor for class Date""" if 0 < month <= 12: # validate month self. month = month else: raise Value. Error("Invalid value for month: %d" % month) if year >= 0: # validate year self. year = year else: raise Value. Error("Invalid value for year: %y" % year) self. day = self. check. Day(day) # validate day print ("Date constructor: ", end="") self. display() def __del__(self): """Prints message when called""" print("Date object about to be destroyed: ", end="") self. display() ……………………………………. . Class Employee: """Employee class with Date attributes""" def __init__(self, first. Name, last. Name, birth. Month, birth. Day, birth. Year, hire. Month, hire. Day, hire. Year): """Constructor for class Employee""" self. birth. Date = Date(birth. Month, birth. Day, birth. Year) self. hire. Date = Date(hire. Month, hire. Day, hire. Year) self. last. Name = last. Name self. first. Name = first. Name print ("Employee constructor: %s, %s" % (self. last. Name, self. first. Name)) def __del__(self): """Called before Employee destruction""" print("Employee object about to be destroyed: %s, %s" % (self. last. Name, self. first. Name)) def display(self): """Prints employee information""" print ("%s, %s" % (self. last. Name, self. first. Name)) print ("Hired: ", end="") self. hire. Date. display() print ("Birth date: ", end="") self. birth. Date. display()
Data Abstraction and Information Hiding Classes and Data Abstractions Abstract Data type (ADT) is a type (or class) for objects whose behaviour is defined by a set of value and a set of operations. An ADT actually captures two notions: A data representation and the operations that can be performed on that data.
Functions as Objects def apply. To. Each(L, f): for i in range(len(L)): L[i] = f(L[i]) Classes and Data Abstractions
Functions as Objects def apply. To. Each(L, f): for i in range(len(L)): L[i] = f(L[i]) L = [1, -2, 3. 33] print('L =', L) apply. To. Each(L, abs) print('L =', L) apply. To. Each(L, int) print('L =', L) Classes and Data Abstractions
Classes and Data Abstractions Functions as Objects def apply. To. Each(L, f): for i in range(len(L)): L[i] = f(L[i]) L = [1, -2, 3. 33] print('L =', L) apply. To. Each(L, abs) print('L =', L) apply. To. Each(L, int) print('L =', L) L = [1, -2, 3. 33] L = [1, 2, 3] import math print(list(map(math. sqrt, [66, 53, 0, 94])))
Iterators for i in [1, 2, 3, 4]: for c in "python": for k in {"x": 1, "y": 2}: for line in open("a. txt"): Classes and Data Abstractions The built-in function iter takes an iterable object and returns an iterator. x = iter([1, 2, 3]) print (x) print(next(x)) Iterators are implemented as classes. Here is an iterator that works like built-in range function. class yrange: def __init__(self, n): self. i = 0 self. n = n def __iter__(self): return self def __next__(self): if self. i < self. n: i = self. i += 1 return i else: raise Stop. Iteration() for i in yrange(10): print(i, end="->") Many built-in functions accept iterators as arguments.
Generators Classes and Data Abstractions Generators simplifies creation of iterators. A generator is a function that produces a sequence of results instead of a single value. def yrange(n): i = 0 while i < n: yield i i += 1 for i in yrange(10): print(i, end="->") def fib(n): a, b = 0, 1 for _ in range(n): yield a a, b = b, a + b print(list(fib(10))) def integers(): """Infinite sequence of integers. """ i = 1 while True: yield i i = i + 1 def squares(): for i in integers(): yield i * i def take(n, seq): """Returns first n values from the given sequence. """ seq = iter(seq) result = [] try: for _ in range(n): result. append(next(seq)) except Stop. Iteration: pass return result print(take(5, squares())) # prints [1, 4, 9, 16, 25] pyt = ((x, y, z) for z in integers() for y in range(1, z) for x in range(1, y) if x*x + y*y == z*z) print(take(10, pyt))
Generator Expressions and Generator Expressions are generator version of list comprehensions. They look like list comprehensions, but returns a generator back instead of a list. a = (x*x for x in range(10)) print(a) # it will print <generator object <genexpr> at 0 x 00 F 5 CEB 0> print(sum(a)) # it will print 285 chain – chains multiple iterators together. it 1 = iter([1, 2, 3]) it 2 = iter([4, 5, 6]) itertools. chain(it 1, it 2) [1, 2, 3, 4, 5, 6] izip – iterable version of zip for x, y in itertools. izip(["a", "b", "c"], [1, 2, 3]): . . . print(x, y). . . a 1 b 2 c 3 Classes and Data Abstractions
- Slides: 17