python中的可变数据类型有列表和元组_Python中列表的 += 和 .extend() 的异同

一道Python题

最近有朋友“考”了我一个Python的题:使用+=和.extend()两种方法扩展元组中的列表会发生什么。虽然我对Python中的可变数据类型、不可变数据类型的概念都有较深的理解,并且也对list的+、+=、.extend()、.append()做过性能分析,但是+=和.extend()两者无论在表现(是否为原地址修改)以及性能上都非常近似,所以对两者的区别还没有明确的概念。为了解答这个问题,我我们先直接上代码试验一下:# 创建一个包含列表的元组:

>>> a_tuple = (1, 2, [])

>>> a_tuple[2] += ['a', 'b'] # (1)

Traceback (most recent call last):

File "", line 1, in

a_tuple[2] += ['a', 'b']

TypeError: 'tuple' object does not support item assignment

>>> a_tuple[2].extend(['a', 'b']) # (2)

>>> a_tuple # (3)

(1, 2, ['a', 'b', 'a', 'b'])(1) 通过+=的方法扩展列表出现“元组不支持元素赋值”的报错。

(2) 使用.extend()方法。

(3) 有趣的是,列表被扩展了两次。虽然+=报错,但是却成功修改了列表。

Python中的可变数据类型和不可变数据类型

要解释这个先从Python中的可变数据类型和不可变数据类型谈起。可变数据类型可以在不改变内存地址的情况下对其进行修改。而不可变数据类型只能重新赋值绑定变量,这时变量的内存地址已经发生变化,而原地址的数据在没有被其他变量引用后将被GC(garbage collector)回收:>>> a = 1

>>> id(a) # CPython通过id()查看变量a的内存地址

1942286128

>>> a += 1 # 对变量a进行修改

>>> id(a) # 这时内存地址已经发生变化

1942286160

>>> a_list = [1] # list为可变数据类型

>>> id(a_list)

2170470080648

>>> a_list.append(2)

>>> id(a_list) # 修改后内存地址没有变化

2170470080648

元组不能修改?

学Python时教材里一般都会说元组不能修改,没有.append()、.extend()、.insert()这些方法。没错,元组是不可变数据类型,确实不能修改。但是元组的元素可以是可变数据类型,而元组中保存的实际是可变数据类型的内存地址。所以通过对可变数据类型的修改,元组最终返回的数据是可以变化的。如果了解C语言中“指针”概念的话就很好懂了。

对于list这种可变数据类型,+=和.extend()有什么异同?

还是接上面那个例子:>>> id(a_list)

2170470080648

>>> a_list += [3]

>>> id(a_list) # 通过+=扩展list,内存地址没有变化

2170470080648

>>> a_list.extend([4])

>>> id(a_list) # 通过.extend()扩展list,当然内存地址也不会变化

2170470080648

>>> a_list = a_list + [5] # 会这样写的真是个人才

>>> id(a_list) # 地址发生了变化

2170470080712

这样来说+=和.extend()在修改list时都不会修改地址,那为什么题目中通过这两种方法修改a_tuple中的list会有不同的结果呢?其实Python中两者的行为确实不同:Python中的.extend()就是在原始内存地址上对list进行了扩展,没有改变内存地址,也就不会报错。

+= 在不可变对象中调用.__add__()(和+一致);而在可变对象中调用的是.__iadd__()(原地址修改)。

.__iadd__()实际上已经成功在原地址修改了列表,但是它会对的a_tuple[2]进行重新赋值,而这一步引发了报错,因为元组的元素不能修改。

怎么避免类似的坑?

我认为Tim Peters的《Zen of Python》(Python之禅)里有一句话很经典:There should be one-- and preferably only one --obvious way to do it.

——应当存在一种,而且更应该只有一种最好的解决方案。

所以我的回答是——你基本上不可能记住所有的特例,最简单粗暴的方法就是意识到:当你遇到一个可能的坑,意味着这不是最好的解决方案,那就忘了它,然后记住最好的。在这里就是记住扩展列表用.extend(),忘记+=吧!

附:+、+=、.extend()、.append()的性能分析:import time

def cal_time(func):

def wrapper():

t1 = time.time()

func()

t2 = time.time()

print(t2-t1)

return wrapper

@cal_time

def func_a():

a = []

for x in range(100000):

a = a + [x]

@cal_time

def func_b():

a = []

for x in range(100000):

a += [x]

@cal_time

def func_c():

a = []

for x in range(100000):

a.extend([x])

@cal_time

def func_d():

a = []

for x in range(100000):

a.append(x)

func_a()

func_b()

func_c()

func_d()

Python 3.5.1测试结果:24.90237021446228 # a = a + [x]

0.01898360252380371 # a += [x]

0.02698493003845215 # a.extend([x])

0.013987541198730469 # a.append(x)

参考资料

在总结这篇文章的时候发现其实这个问题早已经在官方文档的FAQ有非常明确的解答了,推荐阅读:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/260285.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简易贪吃蛇小游戏java版_用GUI实现java版贪吃蛇小游戏

本文实例为大家分享了java版贪吃蛇小游戏的具体代码,供大家参考,具体内容如下项目结构新建一个JFrame窗口,作为程序入口public class GameStart{public static void main(String[] args) {JFrame jFrame new JFrame();jFrame.setBounds(100,100,900,720…

几种代价函数

SAD(Sum of Absolute Difference)SAE(Sum of Absolute Error)即绝对误差和 SATD(Sum of Absolute Transformed Difference)即hadamard变换后再绝对值求和 SSD(Sum of Squared Difference)SSE&am…

Markdown文件导出为HTML的小程序

Markdown文件导出为HTML的小程序为什么做 最近把一些学习经验记下来,总结成MarkDown文件,不知不觉已经有12篇了。 Sublime Text 的 MarkDown Preview 插件能够将MarkDown语法转换为HTML,并提供三种预览方式:浏览器预览、保存为HTM…

python制作自动回复脚本_python itchat实现微信自动回复的示例代码

今天在实验楼发现一个特别好玩的,Python 微信库itchat,可以实现自动回复等多种功能,好玩到根本停不下来啊,尤其是调戏调戏不懂计算机的,特别有成就感,哈哈!!代码如下:#codingutf8imp…

pta龟兔赛跑Java_PTA-龟兔赛跑

乌龟与兔子进行赛跑,跑场是一个矩型跑道,跑道边可以随地进行休息。乌龟每分钟可以前进3米,兔子每分钟前进9米;兔子嫌乌龟跑得慢,觉得肯定能跑赢乌龟,于是,每跑10分钟回头看一下乌龟,…

视频压缩算法的相关知识

视频压缩算法的相关知识MPEG-1MPEG 视频压缩编码后包括三种元素:I帧(I-frames)、P帧(P-frames)和B帧(B-frames)。在MPEG编码的过程中,部分视频帧序列压缩成为I帧;部分压缩…

安装MariaDB数据库(未完成)

1转载于:https://www.cnblogs.com/centos7/p/5994533.html

python接口开发django_用 Django 开发接口

环境搭建1、pip install django2.2.0一、django-admin startproject UITESTpython manage.py startapp paltform创建Django项目1. 创建方式:#方式1:终端输入django-admin startproject UITEST#方式2:pycharm中新建django项目在settings.py文件中添加应用…

戒掉dota

立言为证。 每次不想学习想到dota就强迫自己去培养的兴趣。 比如看一本喜欢的书;比如去跑个步;比如研究某个兴趣点写个报告;比如写份随笔。 转载于:https://www.cnblogs.com/hongxia/p/3830348.html

java切入式编程显示屏_C语言嵌入式系统编程修炼之四:屏幕操作

C语言嵌入式系统编程修炼之四:屏幕操作作者:宋宝华 更新日期:2005-07-22汉字处理现在要解决的问题是,嵌入式系统中经常要使用的并非是完整的汉字库,往往只是需要提供数量有限的汉字供必要的显示功能。例如,一个微波炉的LCD上没有必要提供显…

DIV的边距属性在Chrome和IE中的区别

突然间,在Chrome下看起来很整齐的布局,在IE下变成一团糟。为了找出原因,我改动了div的background-color属性。最后,发现同一个DIV的宽度在IE和Chrome下却不一样。这大晚上的,真是怪吓人滴! 之后&#xff0c…

算法之矩阵计算斐波那契数列

算法之矩阵计算斐波那契数列 本节内容 斐波那契介绍普通方式求解斐波那契矩阵概念矩阵求幂矩阵求解斐波那契1.斐波那契介绍 斐波那契数列有关十分明显的特点,那是:前面相邻两项之和,构成了后一项。即f(n)f(n-1)f(n-2),f(0)0,f(1)f(2)1,推导下…

python中去除字符串中首尾空格的函数_Python中去除字符串首尾特定字符的函数:strip()...

Python中strip()函数的作用是去除一个字符串前导和尾部的特定字符,并返回结果字符串。Python中strip()函数默认是删除字符串前导和尾部空格,通过设定参数,也可以去除字符串前导和尾部的其它特定字符。strip()函数的语法格式str.strip( [ char…

SeekBar和RatingBar

1. SeekBar的主要属性 2. OnSeekBarChangeListener 3. RatingBar的主要属性 4. OnRatingBarChangeListener 1. SeekBar的主要属性 2. OnSeekBarChangeListener 1 <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"2 xmlns:tools&qu…

用“Web的思想”做PC客户端

一直在想&#xff0c;用HTML搭建前端页面这么方便&#xff0c;而且效果这么炫&#xff0c;为什么在PC端的软件要如此麻烦呢&#xff1f;就连C#也是&#xff0c;更何况C了。 尽管C有DirectUI这样优秀的图形库&#xff0c;但是开发起来仍然非常吃力。C#的WPF虽然工具链完善&#…

Java点击按钮div缩放_[Java教程]怎样给div增加resize事件

[Java教程]怎样给div增加resize事件0 2016-10-31 11:00:04当浏览器窗口被调整到一个新的高度或宽度时&#xff0c;就会触发resize事件,这个事件在window上面触发,那么如何给div元素增加resize事件&#xff0c;监听div的高度或宽度的改变呢&#xff1f;某位大神用jquery实现的方…

python判断题题库大数据技术_智慧树_大数据分析的python基础_搜题公众号

智慧树_大数据分析的python基础_搜题公众号更多相关问题社会公众可以查阅烟草专卖行政主管部门的监督检查记录。()公民、法人或者其他组织不得利用自动售货机销售烟草制品。()烟草广告中不得有下列情形()。A、社会公益广告B、迁址、换房、更名等启事广告C、表示吸烟有利人体健公…

Java并发中常用同步工具类

为什么80%的码农都做不了架构师&#xff1f;>>> 同步工具类可以是任何一个对象&#xff0c;只要它根据其自身的状态来协调线程控制流。阻塞队列&#xff08;BlockingQueue&#xff09;可以作为同步工具类&#xff0c;其他类型的同步工具类还包括信号量&#xff08;…

Linux平台Oracle多个实例启动说明

环境说明:oracle实例1的SID为orcl(为默认启动的实例),第二个实例的SID为orcl2 启动步骤&#xff1a; 1&#xff09;启动数据库实例完成后&#xff0c;启动数据库监听服务 #lsnrctl start 2&#xff09;切换到需要启动的数据库实例下&#xff0c;如下表示启动的是orcl数据库…

RTMP协议发送H.264编码及AAC编码的音视频,实现摄像头直播

RTMP协议发送H.264编码及AAC编码的音视频&#xff0c;实现摄像头直播 摘要: RTMP协议发送H.264编码及AAC编码的音视频&#xff0c;实现摄像头直播  RTMP&#xff08;Real Time Messaging Protocol&#xff09;是专门用来传输音视频数据的流媒体协议&#xff0c;最初由Macrome…