抽象——人类伟大之始

引言

抽象可能是人类之所以为人的一个重要因素。

先来看一下辞典上对抽象的定义:

抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征的过程。

抽象的艺术弱化了具体事物的描述,强调艺术的本质:表达人的感受;
抽象的知识不会去描述具体的事物,而是描述一类事物的共性和内涵。
在计算机领域,抽象的思想,让人们不用去考虑一个功能的具体细节,而是从更高的视角关注它的性质。

正常情况下,计算机科学中的抽象需要联系面向对象编程 (Object-Oriented Programming,或 OOP) 讲解;但是由于它不是我们要求掌握的,所以我们尝试绕开 OOP 说明 抽象 的概念。

计算机科学中的抽象

要理解计算机中抽象,我们要先说具体
首先,我们定义一个函数,可以将两个数组逐个元素相加,多出来的元素直接放在后面:

def add_lists(list1, list2):
    length1 = len(list1) 
    length2 = len(list2) # 获得两个列表的长度

    newList = [] # 创建一个新的空列表

    i = 0
    while i < min(length1, length2): # 循环到短的那个列表的长度为止
        newList.append(list1[i] + list2[i]) # 两个列表的对应位置一定有元素,直接相加
        i = i + 1

    if length2 > length1: # 如果第二个列表更长,直接把第二个列表的剩余元素插进去
        for i in range(length1, length2):
            newList.append(list2[i])
    else: # 不然的话,把第一个列表的剩余元素插进去
        for i in range(length2, length1):
                newList.append(list1[i])

    return newList

这样的话,如果我们调用 add_list([1,2,3], [4,5,6,7]),我们会得到 [5, 7, 9, 7]

一旦这个函数定义好,我们便将这个函数的实现细节遗忘。我们的脑海中,只剩下了这样的信息:

def add_lists(list1, list2):
    # 输入两个 list
    # 输出两个 list 的和


当我们要定义多个列表加法的时候,我们不是从头开始写,而是使用以上的信息,在之前的基础上进行:

def sum_lists(lists):  
    curr_list = []
    for lst in lists:
        curr_list = add_lists(curr_list, lst)
    return curr_list


有一天,可能 add_lists 的实现方式改变了(比如用了效率更高的实现方式),但是只要它的使用方式没变,你就不需要做任何事情,也不需要关心它究竟作出了什么改变。

当然,实现完 sum_lists 之后,你也只需要留下下列信息:

def sum_lists(lists):
    # 输入一个包含了多个数组的数组
    # 输出所有数组的和


你可以把你写好的函数放到网上,供其他人使用(第三方库本质上就是这样的东西)。读者大部分情况下也不需要知道函数的内容,他只要知道函数的输入输出(使用方法)就可以了。换言之,就是把它看作了一个黑箱。这就是计算机科学中的抽象

关于抽象的一些扯皮

以下是我被问过的一个问题:

我们现在做研究,一般需要精通一个领域内的所有知识之后,再有所贡献。比如,想研究量子物理,需要从基础的数学开始学起,到中学物理、大学物理和更高深的理论,一路走到人类知识的边界,之后才能去突破它。可是,人类现在一直在积累知识,那么会不会有一天,人穷进一生也学不完现有的领域内知识,于是科学的发展就停滞了?

我认为不会。人类的抽象思维可以很好地解决这个问题。

当知识太多的时候,我们可以像之前 add_lists 的例子一样,把它们抽象出来。我们不用知道理论的每一个细节,只需要在更高的视角下知道它在整个体系中的作用即可。这样,知识的成本就被大大降低了。

抽象构筑知识框架的同时,也提供了很自然的分工模式。理论的内容有可能出错,函数的实现方式可能需要优化,所以一定会有人重新去审视它们。人们可以把它们当作黑箱,以它们为基础去突破科学的边界;也会有人专注于深究它们的内容,查看黑箱的内部,进行反思和优化。

曾有位大佬说过,编程就是在书写和组织知识,我表示非常赞同。所以,我们要适时使用抽象的思维,以减轻自己和代码读者的负担。