Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Data Abstraction All Programmers • Compound objects combine primitive objects together • A date: a year, a month, and a day • A geographic position: latitude and longitude • An abstract data type lets us manipulate compound objects as units 61A Lecture 8 Great Programmers • Isolate two parts of any program that uses data: Wednesday, September 14 ! How data are represented (as parts) ! How data are manipulated (as units) • Data abstraction: A methodology by which functions enforce an abstraction barrier between representation and use 2 Rational Numbers Rational Number Arithmetic numerator Example: denominator Exact representation of fractions 3 General Form: 3 * A pair of integers 2 9 nx = 5 ny * 10 dx 21 nx 10 dx nx*ny = dy dx*dy As soon as division occurs, the exact representation is lost! Assume we can compose and decompose rational numbers: Constructor Selectors • make_rat(n, d) returns a rational number x 3 • numer(x) returns the numerator of x 2 • denom(x) returns the denominator of x 3 + = 5 ny + nx*dy + ny*dx = dy dx*dy 3 8_rat.py def add_rat(x, y): """Add rational numbers x and y.""" nx, dx = numer(x), denom(x) ny, dy = numer(y), denom(y) Rational Number Arithmetic Implementation return make_rat(nx * dy + ny * dx, dx * dy) 8_rat.py def mul_rat(x, y): """Multiply rational numbers x and y.""" # Arithmetic return make_rat(numer(x) * numer(y), denom(x) * denom(y)) def add_rat(x, y): def """Add equal_rat(x, y): numbers x and Selectors Constructor rational y.""" """Return whether rational 8_rat.py nx, dx = numer(x), denom(x)numbers x and y are equal.""" return numer(x) * denom(y) ny, dy = numer(y), denom(y)== numer(y) * denom(x) def return add_rat(x, y): make_rat(nx * dy + ny * dx, dx * dy) """Add rational numbers x and y.""" nx, dx = numer(x), denom(x) def mul_rat(x, y): ny, dy = numer(y), denom(y) """Multiply rational numbers x and y.""" return make_rat(nx * dy + *nynumer(y), * dx, dx * dy) return make_rat(numer(x) denom(x) * denom(y)) def eq_rat(x, mul_rat(x, y): y): def """Multiplywhether rational numbersnumbers x and y.""" """Return rational x and y are equal.""" return make_rat(numer(x) * numer(y), denom(x) * denom(y)) return numer(x) * denom(y) == numer(y) * denom(x) def equal_rat(x, y): returnsx aand rational number x """Return whether rationald)numbers y are equal.""" • make_rat(n, # Constructor and selectors return numer(x) * denom(y) == numer(y) * denom(x) Wishful numer(x) returns the numerator of x • thinking from operator import getitem • denom(x) returns the denominator of x def make_rat(n, d): """Construct a rational number x that represents n/d.""" 5 return (n, d) def numer(x): """Return the numerator of rational number x.""" return getitem(x, 0) def denom(x): """Return the denominator of rational number x.""" 4 Page 1 Tuples Page 1 >>> pair = (1, 2) >>> pair (1, 2) A tuple literal: Comma-separated expressions Page 1 >>> x, y = pair >>> x 1 >>> y 2 "Unpacking" a tuple >>> from operator import getitem >>> getitem(pair, 0) 1 >>> getitem(pair, 1) 2 Element selection More tuples next lecture 6 # Combination def mul_rat(x, y): 8_rat.py """Multiplyy): rational numbers x and y.""" def add_rat(x, return rational make_rat(numer(x) numer(y), """Add numbers x *and y.""" denom(x) * denom(y)) # Combination nx, dx = numer(x), denom(x) def ny, equal_rat(x, y): dy = numer(y), denom(y) def return add_rat(x, y): """Return whether rational x and y are equal.""" make_rat(nx * dy + nynumbers * dx, dx * dy) """Add x and return rational numer(x) numbers * denom(y) == y.""" numer(y) * denom(x) nx, dx = numer(x), denom(x) def mul_rat(x, y): ny, dy = numer(y), denom(y) """Multiply rational numbers x and y.""" return make_rat(numer(x) make_rat(nx * dy +* ny * dx, dxdenom(x) * dy) # Constructor and selectors Representing Rational Numbers return numer(y), * denom(y)) def mul_rat(x, y): fromequal_rat(x, operator import def y): getitem """Multiply rational numbers x and x y.""" """Return whether rational numbers and y are equal.""" return make_rat(numer(x) * == numer(y), denom(x) * denom(y)) def return make_rat(n, d): * denom(y) numer(x) numer(y) * denom(x) """Construct a rational number x that represents n/d.""" def equal_rat(x, return (n, d)y): """Return and whether rational numbers x and y are equal.""" # Constructor selectors numer(x) * denom(y) == numer(y) * denom(x) def return numer(x): Construct a tuple the numerator from """Return operator import getitem of rational number x.""" return getitem(x, 0) # Constructor and selectors def make_rat(n, d): def """Construct denom(x): a rational number x that represents n/d.""" fromreturn operator getitem of rational number x.""" """Return the (n, import d) denominator return getitem(x, 1) def make_rat(n, d): def numer(x): """Construct rational of number x that represents """Return the anumerator rational number x.""" n/d.""" return (n, d) # String conversion return getitem(x, 0) return make_rat(nx * dy + ny * dx, dx * dy) def mul_rat(x, Page 1 y): """Multiply rational numbers x and y.""" return make_rat(numer(x) * numer(y), denom(x) * denom(y)) def equal_rat(x, y): """Return whether rational numbers x and y are equal.""" return numer(x) * denom(y) == numer(y) * denom(x) # Constructor and selectors Reducing to Lowest Terms from operator import getitem def make_rat(n, d): """Construct a rational number x that represents n/d.""" Example: return (n, d) def numer(x): """Return the numerator of rational number x.""" 2 3 5 5 return getitem(x, 0) * # String conversion 15 1/3 25 1/25 2 1 # Improved constructor from fractions import gcd def make_rat(n, d): """Construct a rational number x that represents n/d in lowest terms.""" g = gcd(n, d) return (n//g, d//g) Greatest common divisor def denom(x): """Return the denominator of rational number x.""" Improved constructor Select from a tuple ## String conversion return getitem(x, 1) fromstr_rat(x): fractions import gcd def def """Return make_rat(n, d): a string 'n/d' for numerator n and denominator d.""" 7 # String conversion """Construct a rational number x that represents n/d in lowest terms.""" return '{0}/{1}'.format(numer(x), denom(x)) g = gcd(n, d) def str_rat(x): return (n//g, d//g) """Return a string 'n/d' for numerator n and denominator d.""" # Improved constructor return '{0}/{1}'.format(numer(x), denom(x)) from fractions import gcd def make_rat(n, d): # Improved constructor """Construct a rational number x that represents n/d in lowest terms.""" g = gcd(n, d) fromreturn fractions import gcd (n//g, d//g) def make_rat(n, d): """Construct a rational number x that represents n/d in lowest terms.""" Abstraction Barriers Violating g = gcd(n, d) return (n//g, d//g) 8 Abstraction Barriers Does not use constructors Rational numbers in the problem domain mul_rat 5 1 = def str_rat(x): * = * = """Return a string 'n/d' for numerator n and denominator d.""" 6 1/3 2 50 1/25 2 return '{0}/{1}'.format(numer(x), denom(x)) def denom(x): numer(x): str_rat(x): def """Return the the numerator rational number x.""" a string 'n/d'of for numerator n and denominator d.""" """Return denominator of rational number x.""" return getitem(x, getitem(x, 0) '{0}/{1}'.format(numer(x), denom(x)) return 1) add_rat 1 + = def denom(x): 5 10 2 3 denominator 2 of rational number """Return the x.""" return getitem(x, 1) eq_rat Twice! add_rat( (1, 2), (1, 4) ) Rational numbers as numerators & denominators make_rat numer def divide_rat(x, y): denom Rational numbers as tuples tuple return (x[0] * y[1], x[1] * y[0]) getitem No selectors! However tuples are implemented in Python And no constructor! 9 What is Data? 10 Behavior Conditions of a Pair To implement our rational number abstract data type, we used a two-element tuple (also known as a pair). • We need to guarantee that constructor and selector functions together specify the right behavior. What is a pair? • Rational numbers: If we construct x from n and d, then numer(x)/denom(x) must equal n/d. Constructors, selectors, and behavior conditions: • An abstract data type is some collection of selectors and constructors, together with some behavior conditions. If a pair p was constructed from values x and y, then • If behavior conditions are met, the representation is valid. • getitem_pair(p, 0) returns x, and • getitem_pair(p, 1) returns y. You can recognize data types by behavior, not by bits Together, selectors are the inverse of the constructor Generally true of container types. 11 Not true for rational numbers 12 # Improved constructor return '{0}/{1}'.format(numer(x), denom(x)) from fractions import gcd def make_rat(n, d): # Improved constructor """Construct a rational number x that represents n/d in lowest terms.""" g = gcd(n, d) fromreturn fractions import (n//g, d//g)gcd def make_rat(n, d): """Construct a rational number x that represents n/d in lowest Functional Pair Implementation Using aterms.""" Functionally Implemented Pair g = gcd(n, d) # Functional pair return (n//g, d//g) >>> p = make_pair(1, 2) def make_pair(x, y): As long as we do not violate """Return a functional pair.""" the abstraction barrier, >>> getitem_pair(p, 0) # Functional pair def dispatch(m): we don't need to know that 1 if m == 0: pairs are just functions This function def make_pair(x, returny): x represents a pair >>> getitem_pair(p, 1) """Return pair.""" elif m a==functional 1: 2 def dispatch(m): return y if dispatch m == 0: return return x elif m == 1:i): def getitem_pair(p, Constructor is a If a pair p was constructed from values x and y, then y """Returnreturn the element at index i of pair p.""" higher-order function return p(i) dispatch return • getitem_pair(p, 0) returns x, and def getitem_pair(p, i): """Return the element at index i of pair p.""" • getitem_pair(p, 1) returns y. return p(i) Selector defers to the object itself This pair representation is valid! 13 14