SICP-Notes-Lecture 07 Sequence & Data Abstraction

Lecture 07 Sequences & Data Abstraction

These are my notes for SICP(Structure and Interpretation of Computer Programs). Hope they’ll be of some help to you.

Sequence

A sequence is an ordered collection of values.

  • strings: sequence of characters
  • lists: sequence of values of any data type

Sequence Abstraction

  • All sequences have finite length.

  • Each element in a sequence has a discrete integer index.

  • Sequences share common behaviors based on the shared trait of having a finite length and indexed elements(Remember that the elements are indexed from 0).

    • Retrieve an element at a particular position
    • Create a copy of a subsequence
    • Check for membership
    • Concatenate two sequences together
What can you do with sequences?

Get item: get the ith element [i]

>>> lst = [1, 2, 3, 4, 5]
>>> lst[2]
3
>>> lst[-1] #When the index is negative, ‘-’means from right to left.
5
>>> lst[-2]
4
>>> "cs61a"[3]
'1'

Check membership: check if the value of is in in

>>> 3 in [1, 2, 3, 4, 5]
True
>>> 'z' in "socks"
False
>>> 2 + 4 in [7, 6, 5, 4, 3]
True

Slice a subsequence: create a copy of the sequence from i(included) to j(unincluded) [i:j:skip]

>>> lst = [1, 2, 3, 4, 5]
>>> lst[1:4]
[2, 3, 4]
>>> "lolololololol"[3::2]
'ooooo'

Concatenate: combine two sequences into a single sequence +

>>> [1, 2, 3] + [4, 5]
[1, 2, 3, 4, 5]
>>> "hello "  + "world"
"hello world"
>>> [-1] + [0] + [1]
[-1, 0, 1]

Sequence Processing

Iterating through sequences

You can use a for statement to iterate through the elements of a sequence:

for in :

Rules for execution:

For each element in :

  1. Bind it to in current frame

  2. Execute

i = 0
for elem in [8, 9, 10]:
    print(i, ":", elem)
    i += 1
Range

The range function creates a sequence containing the values within a specified range.

range(, , )

Creates a range object from (inclusive) to (exclusive), skipping every element, which is useful for looping.

You may just input one number using range, and when this happens, start = 0 and skip = 1, what you input is the (exclusive).

>>> for e in range(1, 8, 2):
...     print(e)
1
3
5
7  
>>> lst = [8, 9, 10]
>>> for i in range(len(lst)):
...     print(i, ":", lst[i])
0: 8
1: 9
2: 10
List Comprehensions

You can create out a list out of a sequence using a list comprehension:

[ for in if ]

It is similar to a call expression, which will create a local frame and do the execution in the local frame. So, binding to will not change the bindings in its parent frames.

if doesn’t have to be there when it is true all the time.

>>> [x ** 2 for x in [1, 2, 3]]
[1, 4, 9]
>>> [c +0for c in "cs61a"]
['c0', 's0', '60', '10', 'a0']
>>> [e for e in "skate" if e > "m"]
['s', 't']
>>> [[e, e+1] for e in [1, 2, 3]]
[[1, 2], [2, 3], [3, 4]]

Rules for execution

  1. Create an empty result list that will be the value of the list comprehension

  2. For each element in :

    • Bind that element to in the a newly created frame
    • If evaluates to a true value, then add the value of to the result list

Data Abstraction

Description

  • Compound values combine other values together

    • A date: a year, a month, and a day
    • A geographic position: latitude and longitude
  • Data abstraction lets us manipulate compound values as units

  • Isolate two parts of any program that uses data:

    • 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

Rational Numbers (example)

Constructor and Selectors
  • A rational number equals to a numerator dividing a denominator

  • Exact representation as fractions includes a pair of integers. However, as soon as division occurs, the exact representation may be lost!

  • Assume we can compose and decompose rational numbers:

rational(n, d) #returns a rational number x
numer(x) #returns the numerator of x
denom(x) #returns the denominator of x

Here we call rational(n, d) Constructor and call numer(x) and demon(x) Selectors

Rational Numbers Arithmetic Implementation
def mul_rational(x, y):
    return rational(numer(x) * numer(y), denom(x) * denom(y))

def add_rational(x, y):
    nx, dx = numer(x), denom(x)
    ny, dy = numer(y), denom(y)
    return rational(nx * dy + ny * dx, dx * dy)

def print_rational(x):
    print(numer(x), '/', denom(x))
    
def rationals_are_equal(x, y):
    return numer(x) * denom(y) == numer(y) * denom(x)
  • These functions implement an abstract representation for rational numbers and their calculations.
Representing Rational Numbers
def rational(n, d):
    """A representation of the rational number N/D."""
    return [n, d] #Construct a list

def numer(x):
    """Return the numerator of rational number X."""
    return x[0]

def denom(x):
    """Return the denominator of rational number X."""
    return x[1] #Slect item from a list

alternative way

def rational(n, d):
    def slect(name):
        if name == 'n':
            return n
        elif name == 'd':
            return d
    return slect

def numer(x):
    return x('n')

def denom(x):
    return x('d')

In many programming languages, functions can return functions. And when a function returns a function, the returning function keeps a reference to all the variables that it needs to execute, which are declared in the parent function.

That’s exactly what a closure is. It is a bucket of references to variables a function needs to execute which are declared outside its scope.

Reducing to Lowest Terms
from fractions import gcd #Greatest Common Divisor

def rational(n, d):
    """A representation of the rational number N/D."""
    g = gcd(n, d) # Always has the sign of d
    return [n//g, d//g]

Dictionaries

Dictionaries are unordered collections of key-value pairs.

Each value is bound to a key in a dictionary.

message_dict = {
    'name' : 'cuijiacai',
    'age' : '18',
    'sex' : 'male',
    'weight' : '63',
    'height' : '171'}

Dictionary keys do have two restrictions:

  • A key of a dictionary cannot be a list or a dictionary (or any mutable type)
    • This first restriction is tied to Python’s underlying implementation of dictionaries
  • Two keys cannot be equal; There can be at most one value for a given key
    • The second restriction is part of the dictionary abstraction

If you want to associate multiple values with a key, store them all in a sequence value

Manipulation for dictionaries

  • Get item:

    >>> <dictionary-name>[<key>]
    <value>
    
  • Modify:

    >>> <dictionary-name>[<key>] = <value>
    

    If the key exists in the dictionary, this assignment statement will change the value corresponding to this key to the new value to the right of =.

    If the key doesn’t exist in the dictionary, this assignment statement will create a new key-value bond in the dictionary.

    >>> <dictionary-name>.pop(<key>)
    value
    

    The method pop will delete the key-value bond in the dictionary and return the value corresponding to the deleted bond.

    We can still use the built-in function len to get the number of key-value bonds in the dictionary.

  • Compose:

    >>> <dictionary1>.update(<dictionary2>)
    

    The method update will compose two dictionaries together. However, if the key-value bonds in dictionary2 exist in dictionary1, they will replace them.

  • Travel:

    for key, value in <dictionary>.items():
        #iterate over each key-value bond
    for key in <dictionary>.keys():
        #iterate over each key
    for value in <dictionary>.values():
        #iterate over each value 
    

你可能感兴趣的:(SICP,(or,CS61a),Lecture,Notes,python,sicp)