问题来源

当使用py时,总是随手使用list/dict保存一切(尽管仍然有更效率的数据数据结构),因为list/dict足够方便,而且包含了大部分的常用操作。可是最近我发现了一些问题,这些问题可能会导致严重的错误。

一个简单的例子

复制语句是比较常用的语句,但是如果在py中不小心使用了list的复制,那么下面的代码会带来灾难:

a = [0, 1, 2, 3]
b = a
for item in a:b.append(item)
print(b)

如果按照正常的理解,那么b应该是a的双份数据,也就是 b = [0, 1, 2, 3, 0, 1, 2, 3],但是如果你真的运行以上的代码,就会发现CPU会很快上升到100%,为什么会出现这样呢?是不是py的设计缺陷呢?

我们先完成上面的需求,就是把a进行double copy成b,那么正确的写法应该是:

a = [0, 1, 2, 3]
b = a * 2
print(b)

实际上上述代码使用了生成器,对list/dict进行乘法运算时,往往是将其扩展为n倍。注意这里要和numpy中的操作加以区别。

一切皆对象

在Python Reference[1]中关于Data Model的说明中提到,对象是python对数据的抽象,在python的世界里,一切皆对象。其中最基本的数值,字符串,甚至函数都是一个对象,在py中自定义对象时,可以设置callable方法,可以使得对象像函数一样被调用。

每个对象均包含3个基本元素:identify,type,value。其中,对象的id是创建对象时分配的,在其生存期内保持不变,id是内存地址的一个散列值;对象的type也是对象创建时就决定了的,在生命周期内不可变;而value既可能为可变的,又可能为不可修改的,具体情况视其type而定。

Python的built-in function中提供了id()来返回对象的identify value,提供了type()来返回对象的type。

根据Python Reference关于Naming and binding[2]的说明,对象的name是该对象的引用,在这里,“引用”的背后的含义是指对象的name只是对象的一个tag而已,也即是说,python的复制语句实际上并不是真正的复制语句,而是类似于c语言中的指针,指向的是对象的内存地址。

如以下代码所示:

'''
学习中遇到问题没人解答?小编创建了一个Python学习交流QQ群:725638078
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
a = 1
b = a
print(id(a),id(b))

上面的代码中id(a)和id(b)将指向同一个值,也即是两者指向了同一个内存地址,当改变b的值的时候,a同时也会发生改变。

py的‘指针’

在c语言中最让人头疼的一个特性就是指针,指针是为了解决c语言的一些缺陷而设计的,本身非常灵活,于是cpp也继承了c的指针特性,但是并不是所有人都能够用好指针,特别是对于新手,使用指针往往会导致令人崩溃的错误。py在设计时吸取了教训,抛弃了指针特性,但是在写py程序的时候,我仍然能够感觉到ptr in everywhere。

在复制语句的时候,py的表现让人感觉怪异,那么当查看renfrence的复制语句的时候,我们可以发现这么一句话:

Assignment statements are used to (re)bind names to values and to modify attributes or items of mutable objects.

也就是复制语句实际上是一种绑定,是声明了一个指向某个对象的内存地址的‘指针’。那么以下代码便很容易理解了:

a = 1 # int *a = Int(1)
b = a # int *b = a

How to do

那么该如何做来避免上述的问题呢, 有3种常用的方法:

1.引入copy库,注意这里是浅copy

'''
学习中遇到问题没人解答?小编创建了一个Python学习交流QQ群:725638078
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import copy
a = [0, 1, 2, 3]
b = copy.copy(a)
for item in a:b.append(item)
print (a)
print (b)

2.既然一切皆对象,那么使用对象方法重新生成一个:

a = [0, 1, 2, 3]
b = list(a)
for item in a:b.append(item)
print (a)
print (b)

3.切片法,切片会生成一个原对象的一个copy:

a = [0, 1, 2, 3]
b = a[:]
for item in a:b.append(item)
print (a)
print (b)

结尾给大家推荐一个非常好的学习教程,希望对你学习Python有帮助!

Python基础入门教程推荐:更多Python视频教程-关注B站:Python学习者

Python爬虫案例教程推荐:更多Python视频教程-关注B站:Python学习者

Python中list复制引发的问题相关推荐

  1. python 中使用 global 引发了莫名其妙的问题

    定义全局变量的方法: console=None def log_info(logstr): global console if console is None: console = logging.S ...

  2. python如何定义i_如何在Python中使用自定义消息引发相同的Exception?

    如何在Python中使用自定义消息引发相同的Exception? 我的代码中有这个ValueError块: try: do_something_that_might_raise_an_exceptio ...

  3. python中深浅复制的问题

    python中做图像处理,把矩阵A复制给矩阵B,C语言的逻辑就是: B=A 可是在python中这样复制,两者是指向同一个物理地址,导致最终A变化,B也变化.真郁闷.使用: B=A[:,:,:]也是不 ...

  4. python中深浅复制教程

    在python中,等号作用是引用对象地址对应的对象 python中的数据分为可变类型和不可变类型: 可变类型:可列表.字典 不可变数据类型:字符串String.浮点型Float.整型Int.元祖Tup ...

  5. python中怎么复制代码_Python对象怎么引用_Python对象怎么复制代码_一聚教程网

    本次文章要给大家讲解的是Python对象引用及复制代码,相信这也是大家问题比较大的一个点,下面为大家具体整理了操作过程,一起来了解下. 可以说Python没有赋值,只有引用.你这样相当于创建了一个引用 ...

  6. python递归实现文件复制_在python中递归复制文件或目录

    python似乎有复制文件的功能(如shutil.copy)和复制目录的功能(如shutil.copytree),但我没有找到同时处理这两者的功能.当然,检查您是想复制一个文件还是一个目录是很简单的, ...

  7. python中能主动引发异常的是_python--异常处理-主动引发异常-自定义异常类

    一.主动引发异常 并非只有在程序运行出错时才可以引发异常,python允许在代码中使用raise或assert语句主动引发异常. 1.raise语句 1.1基本格式: raise 异常类名 #创建异常 ...

  8. python中的复制、浅拷贝和深拷贝的区别

    (1)直接复制:传递对象的引用(该引用指向变量的存储地址),若原始值改变,则被赋值的b也会做出相同的改变. b = alist (2)浅拷贝:使用copy库中的copy函数,只拷贝父对象,不拷贝子对象 ...

  9. python list 深复制_Python中list的复制及深拷贝与浅拷贝探究

    在Python中,经常要对一个list进行复制.对于复制,自然的就有深拷贝与浅拷贝问题.深拷贝与浅拷贝的区别在于,当从原本的list复制出的list之后,修改其中的任意一个是否会对另一个造成影响,即这 ...

最新文章

  1. JDK17 要来了!会带来什么新特性?不好意思,我还在JDK7 踏步走...
  2. MySQL锁的用法之行级锁
  3. 微信,QQ这类IM app怎么做——谈谈Websocket
  4. HRBUST 1909——理工门外的树——————【离线处理,差分前缀和】
  5. 感恩被救赎——爱是恒久忍耐
  6. ActiveMQ 5.x中的消息持久性
  7. 计算机课奖金计算步骤,计算机二级excel真题:计算员工奖金
  8. 西瓜书《机器学习》决策树IDW3, C4.5公式推导
  9. 跟女朋友约会一般都干些什么?
  10. 广域网协议之PPP,HDLC
  11. 软件签名不一致是什么意思
  12. 基于大数据的智能交通管理管控指挥平台技术方案
  13. 函数对称性常见公式_初中函数公式大全
  14. 用html写简单的座位表,html座位表,随机点名
  15. infinity新标签页失效
  16. 完美兼容IE_Opera_Firefox等主流浏览器的锁定表格的 表头以及表头列
  17. DLNA的几个小实验
  18. QQ样式的在线客服代码
  19. 积木Sketch Plugin:设计同学的贴心搭档
  20. 刷脸支付有助商户自主营销计划节省开支

热门文章

  1. vue+lowdb+express
  2. 入门系列之在Ubuntu上安装Drone持续集成环境
  3. EdgeConneX公司在都柏林数据中心园区新建数据中心
  4. 中兴通讯已在多个国家和地区商用了安全领域的解决方案
  5. java读取InputStream输入流后输出String字符串
  6. sublime text3函数追踪:ctags配置
  7. 从Config文件中读取节点的配置信息
  8. FindFileByContent
  9. Git学习教程(一):git简介
  10. LFS 安装笔记 (二)