dict

Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。举个例子,假设要根据同学的名字查找对应的成绩,如果用list实现,需要两个list:

names = ['Michael', 'Bob', 'Tracy']
scores = [95, 75, 85]

给定一个名字,要查找对应的成绩,就先要在names中找到对应的位置,再从scores取出对应的成绩,list越长,耗时越长。

如果用dict实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢。用Python写一个dict如下:

>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95

为什么dict查找速度这么快?因为dict的实现原理和查字典是一样的。假设字典包含了1万个汉字,我们要查某一个字,一个办法是把字典从第一页往后翻,直到找到我们想要的字为止,这种方法就是在list中查找元素的方法,list越大,查找越慢。

第二种方法是先在字典的索引表里(比如部首表)查这个字对应的页码,然后直接翻到该页,找到这个字。无论找哪个字,这种查找速度都非常快,不会随着字典大小的增加而变慢。
dict就是第二种实现方式,给定一个名字,比如'Michael',dict在内部就可以直接计算出Michael对应的存放成绩的“页码”,也就是95这个数字存放的内存地址,直接取出来,所以速度非常快。
把数据放入dict的方法,除了初始化时指定外,还可以通过key放入:

>>> d['Adam'] = 67
>>> d['Adam']
67

如果key不存在,dict就会报错

>>> d['Thomas']
Traceback (most recent call last):File "<stdin>", line 1, in <module>
KeyError: 'Thomas'

要避免key不存在的错误,有两种办法,一是通过in判断key是否存在:

>>> 'Thomas' in d
False

二是通过dict提供的get()方法,如果key不存在,可以返回None,或者自己指定的value:

>>> d.get('Thomas')
>>> d.get('Thomas', -1)
-1

注意:返回None的时候Python的交互环境不显示结果。
要删除一个key,用pop(key)方法,对应的value也会从dict中删除:

>>> d.pop('Bob')
75
>>> d
{'Michael': 95, 'Tracy': 85}

和list比较,dict有以下几个特点:
查找和插入的速度极快,不会随着key的增加而变慢;
需要占用大量的内存,内存浪费多。
而list相反:
查找和插入的时间随着元素的增加而增加;
占用空间小,浪费内存很少。
所以,dict是用空间来换取时间的一种方法。

dict可以用在需要高速查找的很多地方,在Python代码中几乎无处不在,正确使用dict非常重要,需要牢记的第一条就是dict的key必须是不可变对象。

这是因为dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)。

要保证hash的正确性,作为key的对象就不能变。在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key:

>>> key = [1, 2, 3]
>>> d[key] = 'a list'
Traceback (most recent call last):File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

set

set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。要创建一个set,需要提供一个list作为输入集合:

>>> s = set([1, 2, 3])
>>> s
{1, 2, 3}

注意,传入的参数[1, 2, 3]是一个list,而显示的{1, 2, 3}只是告诉你这个set内部有1,2,3这3个元素,显示的顺序也不表示set是有序的。。

重复元素在set中自动被过滤:

>>> s = set([1, 1, 2, 2, 3, 3])
>>> s
{1, 2, 3}

通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果:

>>> s.add(4)
>>> s
{1, 2, 3, 4}
>>> s.add(4)
>>> s
{1, 2, 3, 4}

通过remove(key)方法可以删除元素:

>>> s.remove(4)
>>> s
{1, 2, 3}

set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:

>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s1 & s2
{2, 3}
>>> s1 | s2
{1, 2, 3, 4}

set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。把list放入set会报错。

再议不可变对象

上面我们讲了,str是不变对象,而list是可变对象。
对于可变对象,比如list,对list进行操作,list内部的内容是会变化的,比如:

>>> a = ['c', 'b', 'a']
>>> a.sort()
>>> a
['a', 'b', 'c']

而对于不可变对象,比如str,对str进行操作呢:

>>> a = 'abc'
>>> a.replace('a', 'A')
'Abc'
>>> a
'abc'

虽然字符串有个replace()方法,也确实变出了'Abc',但变量a最后仍是'abc',应该怎么理解呢?
我们先把代码改成下面这样:

>>> a = 'abc'
>>> b = a.replace('a', 'A')
>>> b
'Abc'
>>> a
'abc'

要始终牢记的是,a是变量,而'abc'才是字符串对象!有些时候,我们经常说,对象a的内容是'abc',但其实是指,a本身是一个变量,它指向的对象的内容才是'abc'
当我们调用a.replace('a', 'A')时,实际上调用方法replace是作用在字符串对象'abc'上的,而这个方法虽然名字叫replace,但却没有改变字符串'abc'的内容。相反,replace方法创建了一个新字符串'Abc'并返回,如果我们用变量b指向该新字符串,就容易理解了,变量a仍指向原有的字符串'abc',但变量b却指向新字符串'Abc'了。

python基础4(来自廖雪峰的官方网站)相关推荐

  1. python基础8(来自廖雪峰的官方网站)

    生成器 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大 ...

  2. python基础7 (来自廖雪峰的官方网站)

    高级特性 迭代 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration). 在Python中,迭代是通过for ... in来 ...

  3. python基础6(来自廖雪峰的官方网站)

    高级特性 切片 取一个list或tuple的部分元素是非常常见的操作.比如,一个list如下: >>> L = ['Michael', 'Sarah', 'Tracy', 'Bob' ...

  4. python基础5(来自廖雪峰的官方网站)

    函数 定义函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 我们以自定义一个求绝对值的 ...

  5. python基础3(来自廖雪峰的官方网站)

    条件判断 完整形式如下: if <条件判断1>:<执行1> elif <条件判断2>:<执行2> elif <条件判断3>:<执行3& ...

  6. python基础2(来自廖雪峰的官方网站)

    list和tuple list Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. >>> classmates = ['Mic ...

  7. python基础1(来自廖雪峰的官方网站)

    转义字符 为了简化,Python还允许用r''表示''内部的字符串默认不转义,eg. >>> print(r'\\\t\\') \\\t\\ 多行 为了简化,Python允许用''' ...

  8. python的本质,讨论 - 廖雪峰的官方网站

    关于 yield: yield一词的意思有 n.产出,产量:v.让步,提供. 所以当我们定义一个生成器函数时(带yield关键字的函数): def Iter(): for i in range(10) ...

  9. python正确方法,方法 - 廖雪峰的官方网站

    在一个对象中绑定函数,称为这个对象的方法. 在JavaScript中,对象的定义是这样的: var xiaoming = { name: '小明', birth: 1990 }; 但是,如果我们给xi ...

最新文章

  1. ThreadLocal的使用场景
  2. React Native 'config.h' file not found
  3. Java 理论与实践: 线程池与工作队列
  4. 长沙中级职称计算机考试时间,湖南土木工程中级职称注册及每年考试时间是什么时候...
  5. uefi引导linux_使用UEFI双重引导Windows和Linux
  6. 10个问题让你快速避开java中的jdbc常见坑
  7. Silverlight 国外技术文章
  8. js调用百度地图搜索功能
  9. mysql查看enum和set值_mysql中的enum和set类型_MySQL
  10. Android Studio Access to '/svn/Tech/!svn/act/e53c1e70-3832-884e-8bd6-c46dc31f049a' forbidden问题解决方法
  11. cmder添加到系统变量中_Cmder详细设置
  12. java程序员待遇怎么样_现在的java程序员薪资待遇怎么样?
  13. 软件测试中英文术语对照表
  14. Spring框架两大核心特征的基本理解
  15. Prometheus(十)Granfana 通过文件配置实现自动化
  16. CS5266AN DEMO与AG9311MAQ DEMO PCB设计与参数对比|Typec转HDMI带PD+U3拓展坞方案
  17. 使用Requests库+re库爬取猫眼电影评分
  18. ACM_置换群 burnside引理 Polya定理
  19. Android获取设备各项信息(设备id、ip地址、设备名称、运行商、品牌、型号、分辨率、处理器、国家码、系统语言、网络类型、oaid、android版本、操作系统版本、mac地址、应用程序签名..)
  20. 【解决】无线网卡windows仍在设置此设备的类配置,代码56解决方法

热门文章

  1. ubuntu下tesseract 4.0安装及参数使用
  2. 关于微信小程序的的总结
  3. Android如何使用NoHttp
  4. PostgreSQL在何处处理 sql查询之二十一
  5. 在Access和 SQL Server中通配符的应用方法
  6. UA MATH564 概率论 公式与定理总结
  7. UA MATH564 概率论V 中心极限定理
  8. windows令牌学习
  9. 使用CUrl断点续传下载Linux内核5.6.2源码
  10. w3cschool教程 - jQuery插件总结