数据抽象

数据抽象

复合简单数据形成复合数据,复合数据可以提高程序的模块化。数据抽象类似于函数抽象,函数抽象将函数的实现细节隐藏起来,函数随时可以被相同行为的函数(其他实现)替换, 这样就分离了函数的实现和使用。同理,数据抽象隔离了一个复合数据的使用和它的构造细节(表示)

数据抽象的基本思想是: 设计程序,使得它们操作抽象的数据,这样,程序对数据只使用必要的部分,不对数据做任何多余的假设。所以,程序需要两个方面,在抽象的数据上进行操作(并且获得必要的部分)和定义具体的表示(构造方法),在sicp中称为选择函数和构造函数。

  • Constructors: functions that build the abstract data type.
  • Selectors: functions that retrieve information from the data type.

抽象屏障

隔离系统中不同的层次,屏障把使用数据抽象的程序(上层)与实现数据抽象的程序(下面)分开,比如:复合数据由a,b组合,复合数据给上层用户使用,提供使用方式,比如func,上层用户不知道a,b,即实现细节,而func的实现细节里由数据a提供的数据抽象的使用方式,且这个使用方式,是不对最上层的用户暴露的。

层次数据和闭包性质

序对提供了构造复合数据的基本“粘结剂”,在Lisp中。

(cons 1 2)  // 表示构造出1,2的序列
(car (cons 1 2)) => 1
(cdr (cons 1 cons(2 3))) => 2 3

cons这种操作和它建立的数据结构,建立的元素本身也是序对的序对,在lisp中,这是表示表结构的基础,有类似cons这种的能力的称为"闭包性质(Closure,名字不好,容易和FP的误会)"。某种组合 数据对象 的操作满足闭包性质,通过组合得到的数据结构对象本身还可以通过同样的操作再进行组合,闭包性质是建立层次性的结构的关键。

In general, a method for combining data values has a closure property if the result of combination can itself be combined using the same method. Closure is the key to power in any means of combination because it permits us to create hierarchical structures — structures made up of parts, which themselves are made up of parts, and so on.

数据复合, 通常有构造器和一些选择器.

Sequence in python

Sequence有许多,使用数据抽象,它们通用的属性或者行为有:

  • length:获取长度(先不考虑无限长序列)
  • element selection:通过索引获得值

列表的操作:列表推导式, 聚合(max,min,将列表值计算只剩下一个),计算(foreach,map,filter,python需要自己实现,不像scala中提供了现成的),判断某个值,切片

Trees和List

也没啥好说的,感觉就是抄的Sicp,用python实现了一下。。。

tree

另外, 树的实现数据结构是利用的Seq 得到的结果也是Seq, 且还可以被构造函数当成参数, 这种能力就是上文说的"闭包"(closure property). 用闭包构造的数据结构具有层次结构, 对它的访问处理往往也是用的递归能力的函数.

基于Seq, 用闭包构建tree, 可以方便的写出对tree遍历, 操作的代码.

举例, 划分树(partition tree) , 基于线段树, 主要用于快速求出(在log(n)的时间复杂度内)序列区间的第k大值。

def partition_tree(n, m):
    """Return a partition tree of n using parts of up to m."""
    if n == 0:
        return tree(True)
    elif n < 0 or m == 0:
        return tree(False)
    else:
        left = partition_tree(n-m, m)
        right = partition_tree(n, m-1)
        return tree(m, [left, right])
def print_parts(tree, partition=[]):
    if is_leaf(tree):
        if label(tree):
            print(' + '.join(partition))
    else:
        left, right = branches(tree)
        m = str(label(tree))
        print_parts(left, partition + [m])
        print_parts(right, partition)
> partition_tree(2, 2)
[2, [True], [1, [1, [True], [False]], [False]]]
def tree(label, branches=[]):
    """Construct a tree with the given label value and a list of branches."""
    for branch in branches:
        assert is_tree(branch), 'branches must be trees'
    return [label] + list(branches)


def label(tree):
    """Return the label value of a tree."""
    return tree[0]


def branches(tree):
    """Return the list of branches of the given tree."""
    return tree[1:]


def is_tree(tree):
    """Returns True if the given tree is a tree, and False otherwise."""
    if type(tree) != list or len(tree) < 1:
        return False
    for branch in branches(tree):
        if not is_tree(branch):
            return False
    return True


def is_leaf(tree):
    """Returns True if the given tree's list of branches is empty, and False
    otherwise.
    """
    return not branches(tree)

Linkedlist

除了用python自带的list, 还可以利用闭包构造出 LinkedList. A linked list is a pair containing the first element of seq and the rest of the seq, the rest is represented by a new LinkedList.

[1, [2, [3, 'empty']]]lispcons很像,几乎没差别

还可以为这个LinkedList 创建选择器, 像取第一个元素, 取除了头部的元素, 取最后一个元素, 取去了最后一个元素的其他元素, 获取某个位置的元素, 且这些选择器多数都是递归的.获取LinkedList的长度, 用递归.

exam prep

# 和leetcode上的某道题很相似
def subset_sum(target, lst):
    """Returns True if it is possible to add some of the integers in lst
    to get target.

    >>> subset_sum(10, [-1, 5, 4, 6])
    True
    >>> subset_sum(4, [5, -2, 12])
    False
    >>> subset_sum(-3, [5, -2, 2, -2, 1])
    True
    >>> subset_sum(0, [-1, -3, 15])     # Sum up none of the numbers to get 0
    True
    """
    if target == 0:
        return True
    elif len(lst) == 0:
        return False
    else:
        a = subset_sum(target - lst[0], lst[1:]) 
        b = subset_sum(target, lst[1:])
        return a or b
    
    
    
    def intersection(lst_of_lsts):
    """Returns a list of distinct elements that appear in every list in
    lst_of_lsts.

    >>> lsts1 = [[1, 2, 3], [1, 3, 5]]
    >>> intersection(lsts1)
    [1, 3]
    >>> lsts2 = [[1, 4, 2, 6], [7, 2, 4], [4, 4]]
    >>> intersection(lsts2)
    [4]
    >>> lsts3 = [[1, 2, 3], [4, 5], [7, 8, 9, 10]]
    >>> intersection(lsts3)         # No number appears in all lists
    []
    >>> lsts4 = [[3, 3], [1, 2, 3, 3], [3, 4, 3, 5]]
    >>> intersection(lsts4)         # Return list of distinct elements
    [3]
    """
    elements = []
    for i in lst_of_lsts[0]:
        condition = True
        for lst in lst_of_lsts[1:]:
            if i not in lst:
                condition = False
        if condition:
            elements = elements + [i]
    return elements


def wordify(s):
    """ Takes a string s and divides it into a list of words. Assume that the last element of the string is a whitespace.
    Duplicate words allowed.
    >>> wordify ('sum total of human knowledge ')
    ['sum', 'total', 'of', 'human', 'knowledge']
    >>> wordify ('one should never use exclamation points in writing! ')
    ['one', 'should', 'never', 'use', 'exclamation', 'points', 'in', 'writing!']
    """
    start, end, lst = 0, 0, []
    for letter in s
        if letter != ' ':
            end = end + 1
        elif start == end :
            start, end = start + 1, end + 1
        else :
            lst +=  [s[start:end]]
            start, end = end + 1, end + 1
    return lst



你可能感兴趣的:(数据抽象)