Python札记 -- 切片赋值
一、疑惑
今天在看《Python Cookbook》第四章Python技巧的4.7小节时,发现一段初看起来让人疑惑的代码。该小节的任务是将一个包含列表(行)的列表,转换成一个新的列表。新的列表包含了同样的行,但是其中一些列被删除或者重新排序了。让人疑惑的代码如下:
listOfRows = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
listOfRows[:] = [[row[0], row[3], row[2]] for row in listOfRows]
竹风不禁疑惑了,这第二行的代码为啥会用 "listOfRows[:] =" 这种写法?直接写成 "listOfRows =" 不行么?这两者间有什么区别呢?
二、线索
疑惑主要集中在对切片进行赋值上。抱着“实践是检验真理的唯一标准”,竹风做了个小实验:
>>> test_li = ['a','b','c','d','e','f'] #进行测试的list
>>> test_li[1:4] #简单的切片操作
['b', 'c', 'd']
>>> id(test_li) #观察一下测试list的id
139718916544776
>>> test_li[1:4] = [1,2] #对切片进行赋值,而且是不对等的赋值
>>> test_li #观察赋值后的list
['a', 1, 2, 'e', 'f']
>>> id(test_li) #id没有变化,说明是在原对象上进行修改
139718916544776
>>>
配合注释来看的话,对切片赋值貌似是在原对象上进行修改。而且值得注意的是,切片赋值还支持元素个数不相等的操作,比如实验中用[1,2]替换了['b','c','d']。
三、真相
那么真相是什么呢,让我们继续实践一下:
>>> listOfRows = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
>>>
>>> li = listOfRows
>>> id(listOfRows)
139718916543336
>>> id(li) #两者的id相同,说明引用了同一个对象
139718916543336
>>> listOfRows = [[row[0], row[3], row[2]] for row in listOfRows]
>>> listOfRows #使用列表推导产生的结果符合预期
[[1, 4, 3], [5, 8, 7], [9, 12, 11]]
>>> li #li没有改变
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
>>> id(listOfRows)
139718916544416
>>> id(li) #两者id不同,说明listOfRows绑定了一个新的对象
139718916543336
>>>
直接使用 "listOfRows =" 的话,产生了一个新的对象,让我们继续看看 "listOfRows[:] =" 的效果:
>>> listOfRows = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
>>>
>>> li = listOfRows
>>> id(listOfRows)
140034137774560
>>> id(li) #两者id一致,引用了同一个对象
140034137774560
>>> listOfRows[:] = [[row[0], row[3], row[2]] for row in listOfRows]
>>> listOfRows #使用切片赋值,达到预期效果
[[1, 4, 3], [5, 8, 7], [9, 12, 11]]
>>> li #li也发生了变化,因为两者绑定的是同一个对象
[[1, 4, 3], [5, 8, 7], [9, 12, 11]]
>>> id(listOfRows)
140034137774560
>>> id(li) #两者的id都没有变化,说明切片赋值实在原对象上修改
140034137774560
>>>
最后的结束语了:列表推导会产生一个新的列表,而不是修改现有的列表。如果需要一个新的对象,那么可以使用 "listOfRows =" 写法。当需要修改一个现有的列表时,最好的办法是将现有列表的内容赋值为一个列表推导,也就是使用"listOfRows[:] =" 写法。简单地说,使用切片赋值可以修改原对象的类容,而不是创建一个新对象。谢谢大家~~
Python札记 -- 切片赋值的更多相关文章
- Python引用拷贝赋值
先安利一个网站,对学习编程很有帮助:http://www.pythontutor.com/ 可以逐行可视化执行代码,具体自行体验啦 这个网站也是我在看别人的博文时候找到的,也先贴上别人的理解吧,我觉得 ...
- python 对象/变量&赋值的几点思考
python 对象/变量 对象 Every object has an identity, a type and a value. An object's identity never changes ...
- Python 的切片为什么不会索引越界?
切片(slice)是 Python 中一种很有特色的特性,在正式开始之前,我们先来复习一下关于切片的知识吧. 切片主要用于序列对象中,按照索引区间截取出一段索引的内容. 切片的书写形式:[i : i+ ...
- 【转】Python中的赋值、浅拷贝、深拷贝介绍
这篇文章主要介绍了Python中的赋值.浅拷贝.深拷贝介绍,Python中也分为简单赋值.浅拷贝.深拷贝这几种"拷贝"方式,需要的朋友可以参考下 和很多语言一样,Python中 ...
- Python札记 -- 装饰器补充
本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...
- python基础——切片
python基础——切片 取一个list或tuple的部分元素是非常常见的操作.比如,一个list如下: >>> L = ['Michael', 'Sarah', 'Tracy', ...
- python中的赋值操作和复制操作
之前一直写C#,变量之间赋值相当于拷贝,修改拷贝变量不会改变原来的值.但是在python中发现赋值操作本质是和C++中的引用类似,即指向同一块内存空间.下面通过一个例子说明: p=[0,1,2,3,4 ...
- python中的赋值操作
参考:https://www.cnblogs.com/andywenzhi/p/7453374.html?tdsourcetag=s_pcqq_aiomsg(写的蛮好) python中的赋值操作“=” ...
- python中切片的理解
Python中什么可以切片 l Python中符合序列的有序序列都支持切片(slice) l 如:列表,字符,元祖 Python中切片的格式 l 格式:[start : end : step] ...
随机推荐
- java多线程详解(7)-线程池的使用
在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, 这样频繁创建线程就会大大降低系 ...
- js和php对bool值的判断区别
一.将一种数据类型转换为bool值时,PHP和JS的转换规则不同 PHP中 当转换为 boolean 时,以下值被认为是 FALSE : 布尔值 FALSE 本身 整型值 0(零) 浮点型值 0.0( ...
- linux修改主机名称
http://blog.csdn.net/qq_20480611/article/details/51017033 ========================================== ...
- city-picker 选择省市县的一个控件,好用。
我觉得好奇怪,这么好一个插件,为什么没有设置值的方法,还是我才疏学浅?? 我看有的人做法是把,把源代码里面的自动扫描机制注释掉 // $(function () { // $('[data-toggl ...
- 怎么用sublime text 3搭建python 的ide
安装目录的Packages目录下的python文件夹下的Python.sublime-build复制以下内容,保存 {"cmd": ["python", &qu ...
- DB2死锁的解决办法
db2 get snapshot for locks on sampledb2 get db cfg for sampledb2 update db cfg using dlchktime 10000 ...
- Servlet知识
1.Servlet概述 2.编写Servlet的开发步骤a.建立标准的JavaWeb应用目录FirstAppWEB-INFclasseslibweb.xmlb.编写一个类,实现javax.servle ...
- linux下不同服务器间数据传输(rcp,scp,rsync,ftp,sftp,lftp,wget,curl)(zz)
linux下不同服务器间数据传输(rcp,scp,rsync,ftp,sftp,lftp,wget,curl) 分类: linux2011-10-10 13:21 8773人阅读 评论(1) 收藏 举 ...
- android 应用笔记
android 应用笔记 android 应用笔记 小书匠 Android 综合教程 Android常用技巧 安卓系统架构 安卓源码开发 安卓驱动 Linux内核 安卓应用开发 Java 教程 tic ...
- vim c++补全
弄了个vim对c++的补全,主要参考自: http://vim.wikia.com/wiki/C%2B%2B_code_completion 首先确定vim编辑.cc或者.cpp文件时当前自动补全 ...