[CS61A]Lecture #10: Containers and Sequences

仅用作个人学习记录
Reference:https://inst.eecs.berkeley.edu/~cs61a

Simple Pairs

经过前面课程的学习,我们已经了解了数值和函数。数字是一种原子数据:我们并不真正认为它们有部分(可再向下划分),而是将它们作为一个整体来处理。但是我们如何处理由其他数据组成的数据?

虽然 python 已经了许多内置处理数据的特性,但是我们通过已有知识表示如何操作由数据组成的数据。

下面的几个例子不是很实用,这些只是对用一个东西表示另一个东西的概念性的训练。

Simple Pairs (Take 1)

这个有一个由数据组成的数据,数值对。用数值对这个容器表示两个数值。我们需要用两个数构建新的数值对、获取数值对中的值。

def pair(a, b):
    """Return a value that represents the ordered pair of
    non-negative integer values (A, B)."""
    return 2**a * 3**b

def left(p):
    return multiplicty(2, p)

def right(p):
    return multiplicty(3, p)

def multiplicty(factor, n):
    """Assuming FACTOR and N are integers with FACTOR > 1, return
    the number of times N may be evenly divided by FACTOR."""
    r = 0
    while n % factor == 0:
        r += 1
        n //= factor
    return r

Another Representation

上面的表示方法只能表示整数的数值对。

def pair(a, b):
    """Return a value that represents the ordered pair of values
    (A, B)."""
    return lambda which: a if which == 0 else b
def left(p):
    """Assuming that P was created by pair(x, y), return the value x."""
    return p(0)
def right(p):
    """Assuming that P was created by pair(x, y), return the value y."""
    return p(1)

改进后,数值对不只适用整数对。但无法修改数值对。

Adding Mutability

def bad_pair(a, b):
    def pair_func(which, v=None):
        if which == 0:
            return a		# Not the right a and b!
        elif which == 1:
            return b
        elif which == 2:
            a = v
        else:
            b = v
    return pair_func

def left(p):
    return p(0)

def right(p):
    return p(1)

def set_left(p, v):
    p(2, v)
    
def set_right(p, v):
    p(3, v)

def test_bad_pair():
    aPair = bad_pair(3, 2)
    set_left(aPair, 5)
    print(left(aPair))

上述代码还有有些问题,pair_func 中的a、b 不是数值对中的a、b。

Python 中的赋值通常在当前执行的环境框架中创建或设置局部变量。由于 elif 语句,python解释器会在pair_func帧中新建名称a、b 。这也就导致left§会返回None。

那如何解决这个问题呢?其实在之前,我们就已经见过了nonlocal

nonlocal a, b #a and b refer to variables in pair's header

我们需要指出我们实际上想要的设置的变量 a 和 b是从 pair_func 函数外部引入的。此外,这些变量必须已经存在于这些祖先框架之一中。

Sequences

术语Sequence通常是指由索引值集合组成的数据结构。

标准 Python 类型中包含几种不同类型的Sequence

在这里插入图片描述

Python 竭尽全力为所有各种序列类型以及它的其他集合类型(包括集合和字典)提供统一的接口。在下面的内容中,会发现对这几种类型的操作方式几乎一致。

元组 tuple:是不可修改的可索引序列。

列表 list:是可修改的可索引序列。

字符串 string:是不可修改的字符串序列。Python 不支持单字符类型,单字符在 Python 中也是作为一个字符串使用。

范围 range:是不可修改的可索引整数序列。

构建序列

在这里插入图片描述

String Literals

def string_literals():
    print('Single-quoted strings may contain "double-quoted strings"')
    print("Double-quoted strings may contain 'single-quoted strings'")
    print("""Triple double quotes allow 'this', "this", and ""this"", as well as newline characters""")
    print('''Triple single quotes allow "this", 'this', and ''this'', as well as newline characters''')
    print("A test of\nescapes\\.")
    print("Some unicode: \u0395\u1f55\u03c1\u03b7\u03ba\u03b1\u2764")
    print(r"In raw strings (starting with 'r'), \escapes are not replaced")

有三种引号:单引号、双引号和三引号。同时存在单引号和双引号的意义是可以在单引号中使用双引号,或在双引号中使用单引号。单、双引号都不能跨行使用,而三引号可以,三引号还允许字符串中可以包含换行符、制表符以及其他特殊字符。在单、双引号中\被认为是换行符,要想要使用特殊字符时需要使用转义符\

在Python3中,所有的字符串都是Unicode字符串。

在字符串前加r,表示这是个原始字符,所见即所得,就可以避免某些情况下使用很多个转义符。

选择与切片

选择是指通过索引提取元素。Python 可以使用反向索引,-1 表示最后一个元素,-2 表示倒数第二个元素。

切片是指提取子序列。但不会改变原有的序列。切片可以接受三个参数:起始索引、终止索引(不包括)、步长。

t = (2, 0, 9, 10, 11) # Tuple
L = [2, 0, 9, 10, 11] # List
R = range(2, 13) # Integers 2-12.
E = range(2, 13, 2) # Even integers 2-12.
S = "Hello, world!" # Strings (sequences of characters)

t[2] == L[2] == 9, R[2] == 4, E[2] == 6
t[-1] == t[len(t)-1] == 11
S[1] == "e" # Each element of a string is a one-element string.

t[1:4] == (t[1], t[2], t[3]) == (0, 9, 10),
t[2:] == t[2:len(t)] == (9, 10, 11)
t[::2] == t[0:len(t):2] == (2, 9, 11), t[::-1] == (11, 10, 9, 0, 2)
S[0:5] == "Hello", S[0:5:2] == "Hlo", S[4::-1] == "olleH"
S[1:2] == S[1] == "e"

Python 可以直接从字符串中提取单个字符。

利用 string 可以轻易完成之前递归实现的数字逆序:

def reverse_digits(n):
    """Assuming N >= 0 is an integer.  Return the number whose
    base-10 representation is the reverse of that of N.
    >>> reverse_digits(0)
    0
    >>> reverse_digits(10)
    1
    >>> reverse_digits(12321)
    12321
    >>> reverse_digits(2222222)
    2222222
    >>> reverse_digits(102)
    201
    """
    return int(str(n)[-1::-1])

序列组合和转换

序列类型可以在需要时相互转换:

list( (1, 2, 3) ) == [1, 2, 3], tuple([1, 2, 3]) == (1, 2, 3)
list(range(2, 10, 2)) == [2, 4, 6, 8]
list("ABCD") = ['A', 'B', 'C', 'D']

可以通过连接较小的序列来构造某些序列(元组、列表、字符串):

A = [ 1, 2, 3, 4 ]
B = [ 7, 8, 9 ]
A + B == [ 1, 2, 3, 4, 7, 8, 9 ]
A[1:3] + B[1:] == [ 2, 3, 8, 9]
(1, 2, 3, 4 ) + (7, 8, 9) == (1, 2, 3, 4, 7, 8, 9)
"Hello," + " " + "world" == "Hello, world"
(1, 2, 3, 4) + 3 # ERROR:TypeError: can only concatenate list (not "int") to list

当元组中嵌套列表时,保存在元组中的是列表的引用,引用不可改变,但是列表值可以变。

>>> c = (0,[1,2],2)
>>> c
(0, [1, 2], 2)
>>> c[1][1] = 4
>>> c
(0, [1, 4], 2)

序列迭代

>>> t = (2, 0, 9, 10, 11)
>>> s = 0
>>> k = 0
>>> while k < len(t):
... x = t[k]
... s += x
... k += 1
>>> print(s)
32

>>> t = (2, 0, 9, 10, 11)
>>> s = 0
>>> for x in t:
... s += x
>>> print(s)
32
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值