Composing Programs 2.4 Mutable Data - 01

伯克利CS 61A的教学用书笔记和一些课程笔记

一些python笔记

01 关于值和函数默认参数值

>>> a = [10]
>>> b = a
>>> a == b
True
>>> a.append(20)    
>>> a == b
True
>>> a
[10, 20]
>>> b
[10, 20]

 b被绑定到a,所以a改变了,b也会改变。

 

>>> a = [10]
>>> b = [10]
>>> a == b
True
>>> b.append(20) 
>>> a
[10]
>>> b
[10, 20]
>>> a == b
False

没有互相绑定,b改变,那么a不会改变,所以最后不相等。

 

>>> a = [10]
>>> b = a
>>> b is a
True
>>> b == a
True
>>> a = [10]
>>> b = [10] 
>>> b is a
False
>>> b == a
True

当a和b通过 = 绑定时,a和b是同一个东西。所以a或者b改变,都会影响到对方。

 

当一个函数有默认参数时,它的默认值是函数值的一部分,不是每次调用该函数时都会重新生成。

def f(s = []):
    s.append(5)
    return len(s)

>>> f()
1
>>> f()
2
>>> f()
3

02 关于list

切片。对一个列表进行切片会复制一个新列表,不会改变原列表(注意list(s) 和 s[:] 等价于 s):

 

浅拷贝。当列表中有嵌套的列表时,如果对最外层的列表进行切片,并不会对嵌套在内层的列表也进行复制,而是指向同一个嵌套的列表,所以不管对新列表中嵌套的列表进行修改还是对原列表中嵌套的列表进行修改,都会对对方产生影响,这样的方式称为浅拷贝。参考下面的图:

 

s = [2, 3]
t = [5, 6]

a = s + [t]
b = a[1:]
a[1] = 9
b[1][1] = 0

>>> print(s)
[2, 3]
>>> print(t)
[5, 0]
>>> print(a)
[2, 9, [5, 0]]
>>> print(b)
[3, [5, 0]]

上面的代码,用[t]建立了一个list,a中包含了t,b中也包含了t,如果在a中或者b中改变了t,那么t以及所有包含了t的list都会改变,这样的原因就是因为浅拷贝,因为[t]相对于t是个嵌套的列表。is检测两者是否是同一个东西,==检测是否是相同值。下面的图同样讲解了浅拷贝:

 

s = [2, 3]
t = [5, 6]

s[0:0] = t
print(s)
s[3:] = t
t[1] = 0
print(s)
print(t)

# 输出
[5, 6, 2, 3]
[5, 6, 2, 5, 6]
[5, 0]

上面的代码,改变了t,但是s中相应的位置没改变,因为没有嵌套列表,没有构成浅拷贝。


append接收一个参数,将该参数添加到列表末尾,参数可以是任何值,比如一个数或者一个列表,如果是列表,就将这个列表作为一个元素(而不是一个副本)添加到目标列表的末尾,只会将目标列表的长度增加 1 ,该方法返回None。extend将会把参数作为一个副本加入目标列表的末尾,也就是将其每个元素都加入列表,对于列表x和可迭代对象y,x += y等价于x.extend(y),比如,如果参数是一个长度为3的列表,那么目标列表的长度就会增加3,同样返回None。注意extend和append函数都会改变list本身。看下面的列子:

t = [1, 2, 3]
print([t])
t[1:3] = [t]
print(t)
t.extend(t)
print(t)

# 输出
[[1, 2, 3]]
[1, [...]]
[1, [...], 1, [...]]
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

上图中第二行的写法表示,t中的后两个元素替换为t自身,也就是t包含了自己(t中的一个元素指向自身),t是一个包含自身的列表(list),所以结果看起来怪怪的,t包含的真正数据只有第一个元素1.

下面更复杂的例子:


上图中,第 7 行,将a添加到a的末尾,一个列表的一个元素是自身,一个列表包含了自身,a的值同样变成了 [1, [2, 3], [4, [5, 6], 7], 7, [...]],而由于append返回None,所以d的值为None。

 

t = [[1, 2], [3, 4]]
t[0].append(t[1:2])
print(t)

# 输出
[[1, 2, [[3, 4]]], [3, 4]]
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

t[0] 表示列表 [1, 2] ,所以 t[0].append 表示给 [1, 2]加上第三个元素,之所以append可以从这个地方加元素进去,是因为t[0]本身是一个列表,append的参数是 t[1:2] 也就是 [3, 4] ,注意[3, 4]是作为列表append进去的,而不是作为单纯的数append进去的,所以t[0] 变成了 [1, 2, [ [3, 4] ] ] 。如果不理解append列表进去和append数进去,看下面的例子。注意append操作的对象必须是个列表。

a = [1, [2], 3]
a[1].append(5)
print(a)

a = [1, [2], 3]
a[1].append([5])
print(a)

# 输出
[1, [2, 5], 3]
[1, [2, [5]], 3]
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

下面是一个关于extend的例子,同样存在浅拷贝:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值