暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

是你认识的列表、字典、元组、集合吗?(下篇) - Python高手成长路(系列)(第1阶段)

好想学Python 2018-06-29
150

我是DJun(小丁),码龄18年,从事IT工作5年,踩过无数“语言”坑最后入坑Python,想通过公众号,把自己的成长经历与经验分享给朋友们。

同名酷安看看号“好想学Python”已开通,欢迎订阅。


本篇摘要

我们了解到Python不仅有整数、浮点数、布尔值、字符串等基本数据类型,还有列表、字典、元组、集合这些基本数据结构。初入门Python的朋友,或许会把“列表”理解为“数组”,或许只记住“字典”有“键”和“值”的对应关系,或许只知道“元组”相当于一个不可变的“列表”,或许只知道“集合”里面的元素都是不重复的,但是真正碰到题目(或者工作中的需求)的时候,却懵圈这“四大件”应该怎么应用起来。

本篇分上、下两篇,将在我们已经了解列表、字典、元组、集合的基本操作的基础上,着重深入对它们特点上的理解,之后在实际应用中可以信手拈来,耍得6666的(手动滑稽)。

文末会附上新的作业题,欢迎在留言区踊跃参与。

往期精选

>>> Python从哪里开始学好呢?

>>> 一道简单的程序题?

>>> 是你认识的列表、字典、元组、集合吗?(上篇) 


在上篇( 查看链接 ),我们讲到对Python变量的深入理解,讲到列表与“切片”、字典与“映射关系”,这些在使用Python开发的过程中都会经常应用到的。

在开始下篇之前,需要补充说明一下Python变量中的字符串驻留机制。

① 测试短字符串:我们对a、b分别赋值'1234',赋值操作后,检查id,发现实际上a跟b都指向同个内存区域,这个区域储存了“1234”这个数据。

② 测试长字符串:我们对a、b分别赋值'1234'*50,赋值操作后,检查id,发现实际上a跟b却指向不同的内存区域,id不一致,但两个区域分别都储存了“1234”这个数据。

测试结果表明,Python支持短字符串的驻留机制。对于短字符串,将其赋值给多个不同的变量时,内存中只有一个副本,多个变量共享这个副本,与其他基本数据类型具有相同的特点。然而这一特点并不适用于长字符串,长字符串不遵守这种驻留机制。

另外值得一提的是,Python 3中自带OrderedDict(有序字典)类,可以通过“from collections import OrderedDict”来导入使用。它的用法跟普通的dict并没有什么区别,但它的特性是,能记住放入字典的键值对的顺序,在输出字典内容的时候可以把顺序输出出来。

接下来将深入元组与“不可变性”、集合与“唯一性”。


03

元组与“不可变性”


对Python tuple(元组)的理解可以很简单,它与list(列表)类似,但不同与list,它有“不可修改”的特性,而且支持Python特有的“拆包”操作。“拆包”操作在基础教程中一般会提到,这里着重讲“不可变性”。

根据我们对Python变量的理解,这里tuple(元组)的“不可变”,是指一旦tuple生成,对tuple内部的每个索引的变量引用将不可变。注意,这一点意味着,如果tuple(元组)内部引用了list(列表)或者dict(字典),被引用的list或dict也是可以被修改的!

我们来看一个具体实例吧。

我们对a、b分别赋值[1, 2]、{1:1, 2:3},再对c、d分别赋值(a, b),赋值操作后,检查c与d的id,发现实际上c跟d指向不同的内存区域,分别储存了(a, b)这个数据。检查c==d,由于内容相同,尽管两者id不同,也会返回True。对c[0](即a的变量引用)作增加元素操作,增加了“3”,c[0]变成了[1, 2, 3],输出c、d发现结果都随之变化了!

只要朋友们理解了Python变量是储存“引用”这一点,也不难理解元组的“不可变性”究竟是哪里“不可变”又是哪里“可变”了。


04

集合与“唯一性”


Python的set,也就是集合,从底层来看,也是我们前面讲dict(字典)时提到的“哈希表”的实现,不同的地方在于,dict的key(键)是唯一的没有重复,而set没有“键值对”这种关系,可以理解为把dict去掉value(值)剩下key(键),就变成了set。

所以在Python中,初始化set的形式,可以是set(),也可以是跟dict类似地使用“{}”花括弧符号。需要千万留意!由于“{}”可以用于初始化set也可以用于初始化dict,唯一区别它究竟是初始化哪一种的方式,就在于上一段所说的,有没有体现“键值对”的关系。

我们来看一个具体实例吧。

我们对a、b分别赋值{1, 2, 3}、{1:1, 2:3, 3:5},使用type()函数检查c与d的类型,发现a是set类的实例,b是dict类的实例。产生这种差别的原因,在于b在初始化时,用“:”冒号指定了1→1、2→3、3→5的映射关系,也就是我们常说的“键值对”。

数学上的集合,我们知道集合内的元素是互不重复的。Python上的set(集合)是模仿了数学上的原理,我们在《一道简单的程序题?》( 查看链接 )的题解里面也是使用到了set这个数据结构,就是利用了元素“唯一性”这一点,如果把一个n位数的每一位分别放入集合中,如果集合中的元素个数跟n一致,就说明这个n位数每个位都是互不相同的,反之则说明这个n位数中存在重复数字位。

set中的元素支持引用对象,因此若能灵活地利用set的“唯一性”,可以解决实际编程中各种非数学性质但存在“唯一”特点的问题。


05

扩展阅读:JSON


JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,常用于Web中传输和储存小型规模的数据。基于文档型的NoSQL数据库MongoDB在网页爬虫应用中相当常见,它在底层应用了JSON的变体,称之为BSON,结合JSON的用法我们可以很轻松地存取MongoDB数据库中的数据。

Python自带的json模块使用起来很简单,通过“import json”导入该模块就可以直接使用了。下面是一个简单的实例,通过dumps()、loads()实现Python基本数据结构(list、dict、int、str等)与JSON结构的字符串之间的互转。


06

扩展阅读:灵活传参


Python 3在函数或方法传参时,可以利用序列类型(list列表,或tuple元组)、字典类型(dict)来实现“灵活传参”。对于序列类型,传参的时候在名字前面加上*(一个星号);对于字典类型,传参的时候在名字面前加上**(两个星号)。

我们用具体实例来说明吧。

① 对于序列类型(*),通过这种操作,Python将自动把序列类型实例中的每个元素按顺序传入参数,在这个具体例子中,效果为a=args[0],b=args[1],args的长度必须与这里定义的函数f的参数个数一致,都是2个,否则报错。

② 对于字典类型(**),通过这种操作,Python将自动把字典类型实例中的每个键值对,按照与参数名的对应关系进行传入参数,在这个具体例子中,效果为a=kwargs.get('a'),b=kwargs.get('b'),kwargs中的key(键)必须与对应的参数名称一致,不能出现函数参数中未出现的名称,否则报错。


最后,向初入门的朋友推荐Python官方指南的“数据结构”这一章节,通过对该章节的学习,即可掌握Python中基础数据结构的基本操作方法,以及各种灵活的用法(将list活用为queue队列、将list活用为stack堆栈,等)。

官方英文原版: https://docs.python.org/3.5/tutorial/datastructures.html

第三方翻译中文版: http://www.pythondoc.com/pythontutorial3/datastructures.html

(由于公众号限制,以上链接请手动复制后在浏览器中打开)



希望本篇可以给感兴趣或者想要学习的朋友们带来帮助哈。 

有其他疑问也请在下方留言提出,会尽力解答~

点击下方“阅读原文”查看更多
文章转载自好想学Python,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论