在Python中,令values=[0,1,2];values[1]=values,为何结果是[0,[...],2]?
转载自:http://www.zhihu.com/question/21000872/answer/16856382
>>> values = [0, 1, 2]
>>> values[1] = values
>>> values
[0, [...], 2]
我预想应当是
[0, [0, 1, 2], 2]
为何要赋值无限次?
Python 没有赋值,只有引用。你这样相当于创建了一个引用自身的结构,所以导致了无限循环。为了理解这个问题,有个基本概念需要搞清楚。
Python 没有「变量」,我们平时所说的变量其实只是「标签」。执行
values = [0, 1, 2]
的时候,Python 做的事情是首先创建一个列表对象 [0, 1, 2],然后给它贴上名为 values 的标签。如果随后又执行
values = [3, 4, 5]
的话,Python 做的事情是创建另一个列表对象 [3, 4, 5],然后把刚才那张名为 values 的标签从前面的 [0, 1, 2] 对象上撕下来,重新贴到 [3, 4, 5] 这个对象上。
至始至终,并没有一个叫做 values 的列表对象容器存在,Python 也没有把任何对象的值复制进 values 去。过程如图所示:
执行
values[1] = values
的时候,Python 做的事情则是把 values 这个标签所引用的列表对象的第二个元素指向 values 所引用的列表对象本身。执行完毕后,values 标签还是指向原来那个对象,只不过那个对象的结构发生了变化,从之前的列表 [0, 1, 2] 变成了 [0, ?, 2],而这个 ? 则是指向那个对象本身的一个引用。如图所示:
要达到你所需要的效果,即得到 [0, [0, 1, 2], 2] 这个对象,你不能直接将 values[1] 指向 values 引用的对象本身,而是需要吧 [0, 1, 2] 这个对象「复制」一遍,得到一个新对象,再将 values[1] 指向这个复制后的对象。Python 里面复制对象的操作因对象类型而异,复制列表 values 的操作是
values[:]
所以你需要执行
values[1] = values[:]
Python 做的事情是,先 dereference 得到 values 所指向的对象 [0, 1, 2],然后执行 [0, 1, 2][:] 复制操作得到一个新的对象,内容也是 [0, 1, 2],然后将 values 所指向的列表对象的第二个元素指向这个复制二来的列表对象,最终 values 指向的对象是 [0, [0, 1, 2], 2]。过程如图所示:
往更深处说,values[:] 复制操作是所谓的「浅复制」(shallow copy),当列表对象有嵌套的时候也会产生出乎意料的错误,比如
a = [0, [1, 2], 3]
b = a[:]
a[0] = 8
a[1][1] = 9
问:此时 a 和 b 分别是多少?
正确答案是 a 为 [8, [1, 9], 3],b 为 [0, [1, 9], 3]。发现没?b 的第二个元素也被改变了。想想是为什么?不明白的话看下图
正确的复制嵌套元素的方法是进行「深复制」(deep copy),方法是
import copy a = [0, [1, 2], 3]
b = copy.deepcopy(a)
a[0] = 8
a[1][1] = 9
在Python中,令values=[0,1,2];values[1]=values,为何结果是[0,[...],2]?的更多相关文章
- 在python中定义二维数组
发表于 http://liamchzh.0fees.net/?p=234&i=1 一次偶然的机会,发现python中list非常有意思. 先看一段代码 [py]array = [0, 0, 0 ...
- python 中的可变对象与不可变对象
近日辞职待工,没有实际的项目与大家分享.暂写写在实际运用python中遇到的关于可变对象和不可变对象的坑. 首先我们需要明确一个概念,在python中一且皆对象.我们一般定义一个变量a=0,其实质a是 ...
- python中sys.exit()和os._exit(0)退出程序
python中退出程序的两种方法,0为默认状态,可以为空,两者均会退出当前运行的程序,os._exit(0)中的0不能省略 sys.exit(0):可以捕获SystemExit异常,然后做相应的清理工 ...
- 在python中使用print()时,raw write()返回无效的长度:OSError: raw write() returned invalid length 254 (should have been between 0 and 127)
写出一个不是code的bug,很烦恼,解决了挺长时间,都翻到外文来看,不过还是解决了,只尝试了一种简单可观的方法,希望对大家有用 我正在使用Django与Keras(tensorflow)来训练一个模 ...
- python中None与0、Null、false区别
None是Python中的一个关键字,None本身也是个一个数据类型,而这个数据类型就是None,它可0.空字符串以及false均不一样,这些都只是对象,而None也是一个类. 给个bool测试: v ...
- python中的0,None,False,空容器
在Python中,None.空列表[].空字典{}.空元组().0等一系列代表空和无的对象会被转换成False.除此之外的其它对象都会被转化成True. 1.0等于False,这点要注意. 2.空的l ...
- 初学者必知的Python中优雅的用法 分类: Python 2015-05-11 15:02 782人阅读 评论(0) 收藏
本文由 伯乐在线 - 淘小米 翻译,Daetalus 校稿.未经许可,禁止转载!英文出处:freepythontips.wordpress.com.欢迎加入翻译小组. Hi 朋友们.由于我最近都比较忙 ...
- Python中的X[:,0]和X[:,1]
https://blog.csdn.net/csj664103736/article/details/72828584 python中 x=x[1:] 是什么意思 将x的第二位到最后一位的内容赋给x. ...
- Python 中的0 和 1 的意思
Python程序语言指定任何非0和非空(null)值为true,0 或者 null为false,所以Python中的 1 代表 True,0代表False
随机推荐
- 计算excel列的名字
#include <iostream> using namespace std; int main() { unsigned int column; cin>> ...
- 时钟 IoTimer
/* 例程是在运行在DISPATCH_LEVEL的IRQL级别 例程中不能使用分页内存 另外在函数首部使用 #pragma LOCKEDCODE */ #include "Driver.h& ...
- FloatingActionButton增强版,一个按钮跳出多个按钮--第三方开源--FloatingActionButton
FloatingActionButton项目在github上的主页:https://github.com/futuresimple/android-floating-action-button F ...
- C++及数据结构笔试面试常见知识点总结
一些常考的基础知识点个人总结,大神勿喷,欢迎指正. 1.广义表的表尾是指除去表头后剩下的元素组成的表,表头可以为表或单元素值.表尾或为表,或为空表. 2.构造函数不能声明为虚函数. 构造函数为什么不能 ...
- idea修改jsp后不会自动编译和替换(转)
使用IntelliJ IDEA开发JavaWeb项目时,修改了JSP后刷新浏览器无法及时显示修改后的页面? 解决办法:tomcat配置中,On frame deactivation属性选择Update ...
- jquery的监听事件和触发事件
监听事件 $(selector).on('Event me',function(e){ //do something }) 触发事件 $(selector).trigger('Event name') ...
- Html获取经纬度
if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( function success(pos) {alert( ...
- Notification通知栏
Notification通知栏 首先实现的功能就是通知栏显示Notification,Notification是显示在系统的通知栏上面的,所以Notification 是属于进程之前的通讯.进程之间的 ...
- treap模版代码
treap模版暂存. 以后修改整理. #include<cstdio> #include<iostream> #include <time.h> #include& ...
- hdu 2085
PS:递推题.. a[n]=a[n-1]*3+2*b[n-1] b[n]=a[n-1]+b[n-1] 代码: #include "stdio.h" ]; ]; int main ...