大爽Python入门教程 6-1 变量进阶 可变`mutable`、不可变`immutable`

大爽Python入门公开课教案 点击查看教程总目录

1 可变与不可变

先来观察下两段代码,
看下这两段代码的区别。

  1. 片段一
>>> x = 10
>>> y = x
>>> x = 5
>>> y
10
  1. 片段二
>>> a = [1, 2, 3]
>>> b = a
>>> a[0] = 5
>>> b
[5, 2, 3]

简单分析会发现:
1中y不随x的变化而变化。
2中b随着a的变化而变化。

这样的情况,其缘由是可变对象mutable objects
和不可变对象immutable objects
python中的常见的对象情况如下

  • 不可变对象:intfloatboolstrtuple
  • 可变对象:listdict

可变对象和不可变对象的本质区别;引用和值。
但这个介绍深了,就比较麻烦,感觉甚至涉及到c语言中的指针。

这里我选择用一种相对浅显,而又直观的方式
帮助大家理解这个可变对象和不可变对象。

片段一过程图示如下

片段二过程图示如下

补充:右边数字图标所在箭头,对应左边数字图标那一行代码执行效果。

通过这个图示,大家应该容易想明白:
片段一,第三句直接让x变量指向了新的对象(值)。
片段二,第三句只是让x变量的内部属性(变量) 指向了新的对象(值),xy还是对应的原本的对象(值)。

同理有

>>> c = {"a": 1, "b": 2}
>>> d = c
>>> d["a"] = 5
>>> c
{'a': 5, 'b': 2}

2 函数传参中的变化

猜一猜以下两段代码的输出是多少。

  1. 片段一
def change_one(y):
    y = 5

x = 10
change_one(x)
print(x)
  1. 片段二
def change_two(b):
    b[0] = 5

a = [1, 2, 3]
change_two(a)
print(a)

片段一的输出为10
片段二的输出为[5, 2, 3]

其原理和第一部分的可变对象不可变对象是一样的。

更细来讲,就是函数调用的时候,有一个隐藏的赋值操作。
把实参赋值给了形参。
即片段一调用代码change_one(x)中有赋值操作y=x,
即片段二调用代码change_two(a)中有赋值操作b=a

由片段二,我们其实能发现一个问题。
就是把列表或者字典传到函数中的话,
函数内部如果修改了列表变量或字典变量,
会导致外面的也会更着变化,
这在很多时候会出问题。

3 复制拷贝(copy)

为了保证函数内,
对列表或字典的修改,
不会污染函数外,
我们常常会使用拷贝
即新建一个内容一样的列表或字典。

根据现有知识,拷贝列表操作有以下几种

使用循环拷贝列表

x = [1, 2, 3, 4]
# copy start
x_copy = []
for item in x:
    x_copy.append(item)
# copy done

使用切片拷贝列表

使用切片,能得到一个新的序列。

x = [1, 2, 3, 4]

x_copy = x[:] # copy done

显然,使用切片更高效。

通过循环拷贝字典

根据目前掌握的知识,暂时只能通过循环来拷贝字典

c = {"a": 1, "b": 2}
# copy start
c_copy = {}
for k in c:
    c_copy[k] = c[k]
# copy done

效果

拷贝之后,
修改原来的不会影响到新的,
修改新的也不会影响到缘来的。
示例如下

def change_three(n)
    n_copy = n[:]
    n_copy[0] = 10

m = [1, 2, 3, 4]
change_three(m)
print(m)

输出为

[1, 2, 3, 4]
posted @ 2021-11-29 21:49  大爽歌python编程辅导  阅读(70)  评论(0编辑  收藏  举报