SICP in Python 读书笔记(一)

Posted by Waynerv on

category: Python

Tags: 计算机基础

第一章 使用函数构建抽象

1.5 控制

语句和符合语句

  1. 语句(statement)不会被求值(evaluated),而是被执行(excuted)。

局部赋值

  1. 无论什么时候执行 return 语句,函数调用的流程都会中止。
  2. 函数只能操作局部作用域的事实是创建模块化程序的关键。

条件语句

  1. if语句中elif和else子句都是可选的。
  2. boolean contexts: their truth values matter to control flow, but otherwise their values can never be assigned or returned.

迭代

  1. 所有 = 右边的表达式会在绑定发生之前求出来。
  2. 为了防止 while子句的语句组无限执行,它应该总是在每次通过时修改环境的状态

测试

  1. assert语句:表达式为假时,输出逗号后的字符串。
  2. 只调用一个函数的测试叫做单元测试。
  3. 运行文档中所有doctest:
python3 -m doctest <python_source_file>

1.6 高阶函数

我们应该从强大的编程语言索取的东西之一,是通过将名称赋为常用模式来构建抽象的能力,以及之后直接使用抽象的能力。

函数作为参数

略……

函数作为通用方法

  1. 命名和函数允许我们抽象而远离大量的复杂性。当每个函数定义不重要时,且求值过程触发的计算过程相当复杂,我们并不需要展示所有东西。
  2. 将小的组件组合在复杂的过程中,我们可以拥有非常通用的求值过程。

嵌套定义

严格来说,内部函数能够访问定义所在环境(而不是调用所在位置) 的名称————闭包

  1. 每个用户定义的函数都有一个关联环境:它的定义所在的环境。
  2. 当一个用户定义的函数调用时,它的局部帧扩展于函数所关联的环境。
  3. 局部函数的名称并不影响定义所在函数外部的名称,因为局部函数的名称绑定到了定义处的当前局部环境中,而不是全局环境。
  4. 局部函数可以访问外层函数的环境。这是因为局部函数的函数体的求值环境扩展于定义处的求值环境。

作为返回值的函数

带有词法作用域的编程语言的一个重要特性就是,局部定义函数在它们返回时仍旧持有所关联的环境

Lambda表达式

Lambda 表达式是函数体具有单个返回表达式的函数,++不允许出现赋值和控制语句++

   lambda           x        :       f(g(x))
"A function that takes x and returns f(g(x))"

装饰器

CODE:

>>> def trace1(fn):
        def wrapped(x):
            print('-> ', fn, '(', x, ')')
            return fn(x)
    return wrapped
>>> @trace1
    def triple(x):
        return 3 * x
>>> triple(12)
-> <function triple at 0x102a39848> ( 12 )
36
triple = trace1(triple)

第二章 使用对象构建抽象

2.1 引言

对象隐喻

对象也拥有方法,它是值为函数的属性。 - 方法:特定的函数 - 函数:区别与数值 - 属性:包括方法和数值

in Python every value is an object

原始数据类型

原始数据类型具有以下特性: 1. 这些类型的对象可以求值为原始表达式,叫做字面值。 2. 存在内建的函数、运算符和方法可以操作这些对象。

2.2 数据抽象

数据抽象是一种方法论,使我们将复合数据对象的使用与它的具体构造方式相隔离 选择器和构造器

有理数的算数

None

元组

多重赋值的本质是创建和解构元组 通过元组、选择函数和构建函数实现了有理数的实现、计算和打印

抽象界限

抽象界限划分抽象的边界,因为它们仅仅依赖于上层的表现(通过使用) 和底层的实现(通过定义)。 分层传递

数据特性

通常,我们可以将抽象数据类型当做一些选择器和构造器的集合,并带有一些行为条件 偶对的构建

def make_pair(x, y):
    """Return a function that behaves like a pair."""
    def dispatch(m):
        if m == 0:
            return x
        elif m == 1:
            return y
    return dispatch
def getitem_pair(p, i):
    """Return the element at index i of pair p."""
    return p(i)
p = make_pair(1, 2)
p(0)
p(1)

函数当做值来操作的能力,提供给我们表示复合数据的能力

2.3 序列

序列不是特定的抽象数据类型,而是不同类型共有的一组行为。 具有的共性: 1. 特定长度 2. 通过下标进行元素选择

嵌套偶对

元组封闭性:可以包含自己本身作为元素

递归列表

>>> empty_rlist = None
>>> def make_rlist(first, rest):
"""Make a recursive list from its first element and the rest."""
return (first, rest)
>>> def first(s):
"""Return the first element of a recursive list s."""
return s[0]
>>> def rest(s):
"""Return the rest of the elements of a recursive list s."""
return s[1]
>>> def len_rlist(s):
"""Return the length of recursive list s."""
length = 0
while s != empty_rlist:
s, length = rest(s), length + 1
return length
>>> def getitem_rlist(s, i):
"""Return the element at index i of recursive list s."""
while i > 0:
s, i = rest(s), i - 1
return first(s)

getitem_rlist_2

序列迭代

for <name> in <expression>:
<suite>

序列抽象

  • 成员性

所有序列都有叫做 index 和 count的方法,它会返回序列中某个值的下标(或者数量) - 切片

任何边界上的省略都被当作极限值

字符串

  • 字符串满足两个基本的序列条件:拥有长度并且支持元素选择
  • 字符串的元素本身就是包含单一字符的字符串。不像许多其它编程语言那样,Python没有单独的字符类型,任何文本都是字符串,表示单一字符的字符串长度为 1。
  • 成员性 字符串上实现了成员性运算符 in,但是与序列上的实现具有完全不同的行为,它匹配子字符串而不是元素。字符串上的 count 和 index方法接受子串作为参数,而不是单一字符。count 统计字符串中非重叠字串的出现次数。
  • 强制字符串 str 函数可以以任何类型的参数调用,并返回合适的值

    约定接口

numerate  filter map   accumulate
--------- ------ ----- ----------
words     iscap  first    tuple

将程序表达为序列操作有助于我们设计模块化的程序

map、filter、reduce函数的用法

<map expression> for <name> in <sequence expression> if <filter expression>

生成器表达式生成可迭代对象(迭代器)

2.4 可变数据

局部状态

nonlocal语句的用法()

非局部赋值的好处

重新调用make_withdraw,会产生一个新的局部帧,不影响在全局帧中绑定到名称 wd 的第一个 withdraw。 重新调用make_withdraw 重复调用withdraw

非局部赋值的代价

即使我们通过取钱来修改了余额,某个银行账户还是“相同”的银行账户。 相反,我们可以让两个银行账户碰巧具有相同的余额,但它们是不同的对象。

列表

身份是个比相等性更强的条件 两个对象当且仅当在内存中的位置相同时为同一个对象。CPython 的实现直接比较对象的地址来确定。 列表解析式的用法:

>>> from unicodedata import lookup
>>> [lookup('WHITE ' + s.upper() + ' SUIT') for s in suits]
['♡', '♢', '♤', '♧']

列表的实现:

def make_mutable_rlist():
    """Return a functional implementation of a mutable recursive list."""
    contents = empty_rlist
    def dispatch(message, value=None):
        nonlocal contents
        if message == 'len':
            return len_rlist(contents)
        elif message == 'getitem':
            return getitem_rlist(contents, value)
        elif message == 'push_first':
            contents = make_rlist(value, contents)
        elif message == 'pop_first':
            f = first(contents)
            contents = rest(contents)
            return f
        elif message == 'str':
            return str(contents)
    return dispatch

字典

字典是无序的键值对集合 - 字典的键不能是可变内建类型的对象 - 一个给定的键最多只能有一个值 字典的实现:

def make_dict():
    """Return a functional implementation of a dictionary."""
    records = []
    def getitem(key):
        for k, v in records:
            if k == key:
                return v
    def setitem(key, value):
        for item in records:
            if item[0] == key:
                item[1] = value
                return
        records.append([key, value])
    def dispatch(message, key=None, value=None):
        if message == 'getitem':
            return getitem(key)
        elif message == 'setitem':
            setitem(key, value)
        elif message == 'keys':
            return tuple(k for k, _ in records)
        elif message == 'values':
            return tuple(v for _, v in records)
    return dispatch

注:转载本文,请与作者联系




如果觉得文章对您有价值,请作者喝杯咖啡吧

|
donate qrcode

欢迎通过微信与我联系

wechat qrcode

0 Comments latest

No comments.