概述

什么是数据

数据即变量的值,如name = 'John'John则是我们保存的数据。

Python3 中有六个标准的数据类型:

  • Number(数值)
  • String(字符串)
  • List(列表)
  • Tuple(元组)
  • Sets(集合)
  • Dictionary(字典)

数值

Python的数值类型包括常规的类型:整数(没有小数部分的数字)、浮点数(通俗地说,就是有小数部分的数字)以及其它数值类型(复数、分数、有理数、无理数、集合、进制数等)。除了十进制整数,还有二进制数、八进制数、十六进制数。

需要说明的:

  • Python 3.x中的整数不区分一般整数和长整型整数,3.x版本中的整数支持无穷精度
  • 任何时候浮点数都是不精确的。当带有小数点或科学计数的标记符号e或E,就表示这是浮点数;
  • 当浮点数参与表达式的运算时,会以浮点数的规则进行运算,也就是整数会转换成浮点数类型
  • 数值类型是不可变对象,不可变意味着不可原处修改;

数值类型不可变说明:假如a = 3333,那么现在内存中会有一个内存块保存数值对象3333,如果修改它,比如对它加上1操作a += 1,python将创建一个新的内存块用来保存新的数值对象3334,而不是在3333那个内存块中直接修改为3334,所以那个原始的数值3333就被丢弃了,它会等待垃圾回收器去回收。

布尔

Python中True表示真,False表示假,这两个值是数值1和0的字符串表示格式:

1
2
3
4
5
6
7
8
>>> type(True)
<class 'bool'>
>>> type(False)
<class 'bool'>
>>> bool(0)
False
>>> bool(1)
True

同时,bool类型是int类型的一个子类:

1
2
>>> bool.__bases__
(<class 'int'>,)

哪些数据是False

  • 整数值0、浮点数值0.0等、空字符串都为假;
  • None为假;
  • 空数据对象都是假,比如[]{}()等;

Tips:None为假,它不是表示对象为空,也不是表示对象未定义。它自身就是一个实实在在的数据对象,在内存中有自己的内存地址**,而且整个python全局只有一个唯一的None对象。可以认为,None是一种特殊的数据对象,像数值1、字符串’a’一样,只不过内存中这个数据对象里面存储的数据是我们不得而知的,但它永远表示为False。在Python中,没有显式定义return语句的函数、方法并不意味着没有返回值,它们的默认返回值是None

字符串

字符串(String):一个有序的字符集合,用来存储和表现基于文本的信息,要求使用单引号或双引号括起来。使用双引号的一个好处,就是字符串中可以使用单引号字符。例如:

1
2
3
4
5
6
7
8
>>> a="I'm a dog."
>>> a
"I'm a dog."
>>> a='I'm a dog.'
File "<stdin>", line 1
a='I'm a dog.'
^
SyntaxError: invalid syntax

字符串是“不可变的”,它不能被更改。尝试对字符串中的一个字符重新赋值,将导致TypeError错误。例如:

1
2
3
4
5
>>> a=r"It's a cat"
>>> a[5]='an'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

转义

反斜杠\可以用来转义

1
2
3
4
5
6
7
>>> 'desn't'
File "<stdin>", line 1
'desn't'
^
SyntaxError: invalid syntax
>>> 'desn\'t'
"desn't"

如果你不希望前置了\的字符转义成特殊字符,可以使用原始字符串 方式,在引号前添加r即可:

1
2
3
4
5
>>> print('C:\some\name')
C:\some
ame
>>> print(r'C:\some\name')
C:\some\name

按下标取值

字符串是可以被索引(下标访问)的,第一个字符索引是0。单个字符并没有特殊的类型,只是一个长度为一的字符串。

1
2
3
4
5
>>> a="hello world!"
>>> a[1]
'e'
>>> a[5]
' '

切片

1
2
3
>>> a="hello world!"
>>> a[3:7]
'lo w'

长度

1
2
3
>>> a="hello world!"
>>> len(a)
12

in和not in

1
2
3
4
5
6
7
>>> a="hello world!"
>>> 'a' in a
False
>>> 'e' in a
True
>>> 'a' not in a
True

跨行连续输入

字符串字面值可以跨行连续输入。一种方式是用三重引号:"""..."""'''...'''。字符串中的回车换行会自动包含到字符串中,如果不想包含,在行尾添加一个\即可。

1
2
3
4
5
6
7
8
>>> print("""\
... Usage: thingy [OPTIONS]
... -h Display this usage message
... -H hostname Hostname to connect to
... """)
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to

拼接

字符串可以用+进行连接,也可以用*进行重复。

1
2
3
4
5
6
>>> a='haha'
>>> b='lala'
>>> a+b
'hahalala'
>>> a*3
'hahahahahaha'

相邻的两个或多个字符串字面值(引号引起来的字符)将会自动连接到一起。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> 'hi''story'
'history'

# 只能对两个字面值这样操作,变量或表达式不行
>>> c='hi'
>>> c'story'
File "<stdin>", line 1
c'story'
^
SyntaxError: invalid syntax

# 如果想连接变量,或者连接变量和字面值,可以用 + 号
>>> c+'story'
'history'

字符串的方法

转换大小写

upper()和lower()字符串方法返回一个新字符串,其中原字符串的所有字母都被相应地转换为大写或小写。字符串中非字母字符保持不变。

1
2
3
4
5
>>> a = 'Hello world!'
>>> a.upper()
'HELLO WORLD!'
>>> a.lower()
'hello world!'

Tips:这些方法没有改变字符串本身, 而是返回一个新字符串。如果你希望改变原来的字符串, 就必须在该字符串上调用upper()lower(),然后将这个新字符串赋给保存原来字符串的变量,如a=a.upper()

判断大小写

如果字符串至少有一个字母, 并且所有字母都是大写或小写,isupper()islower()方法就会相应地返回布尔值True。否则, 该方法返回False

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> a = 'Hello world!'
>>> a.isupper()
False
>>> a.islower()
False
>>> b='a dog'
>>> b.islower()
True
>>> b.isupper()
False
>>> c='AAA'
>>> c.isupper()
True
>>> c.islower()
False

isX字符串方法

除了islower()isupper(), 还有几个字符串方法,它们的名字以is开始。下面是一些常用的isX字符串方法:

  • isalpha()返回True,如果字符串只包含字母,并且非空;
  • isalnum()返回True,如果字符串只包含字母和数字,并且非空;
  • isdecimal()返回True,如果字符串只包含数字字符,并且非空;
  • isspace()返回True,如果字符串只包含空格、制表符和换行,并且非空;
  • istitle()返回True,如果字符串仅包含以大写字母开头、后面都是小写字母的单词;

判断开始的字符串和结束的字符串

startswith()endswith()方法返回True,如果它们所调用的字符串以该方法传入的字符串开始或结束。否则,方法返回False

1
2
3
4
5
6
7
8
9
>>> a="I'm a dog."
>>> a.startswith("I'm")
True
>>> a.startswith("you")
False
>>> a.endswith("dog.")
True
>>> a.endswith("cat.")
False

字符串连接

如果有一个字符串列表,需要将它们连接起来,成为一个单独的字符串,join()方法就很有用。join()方法在一个字符串上调用,参数是一个字符串列表,返回一个字符串。返回的字符串由传入的列表中每个字符串连接而成。

1
2
3
4
>>> ','.join(['dog','cat','fish'])
'dog,cat,fish'
>>> ' '.join(['dog','cat','fish'])
'dog cat fish'

字符串分割

split()方法针对一个字符串调用,返回一个字符串列表。

1
2
>>> "I'm a dog".split()
["I'm", 'a', 'dog']

对齐文本

rjust()ljust()字符串方法返回调用它们的字符串的填充版本,通过插入空格来对齐文本。这两个方法的第一个参数是一个整数长度,用于对齐字符串。

1
2
3
4
>>> 'dog'.rjust(10)
' dog'
>>> 'dog'.ljust(10)
'dog '

rjust()ljust()方法的第二个可选参数将指定一个填充字符,取代空格字符。

1
2
>>> 'dog'.rjust(10,'*')
'*******dog'

center()字符串方法与ljust()rjust()类似,但它让文本居中,而不是左对齐或右对齐。

1
2
>>> 'dog'.center(20,'=')
'========dog========='

删除空白字符

strip()字符串方法将返回一个新的字符串,它的开头或末尾都没有空白字符。lstrip()rstrip()方法将相应删除左边或右边的空白字符。

1
2
3
4
5
6
7
>>> a = ' Hello World '
>>> a.strip()
'Hello World'
>>> a.lstrip()
'Hello World '
>>> a.rstrip()
' Hello World'

替换字符串

replace()方法把字符串中的old(旧字符串) 替换成 new(新字符串),如果指定第三个参数max,则替换不超过max 次。

语法格式如下:

1
str.replace(old, new[, max])

例如:

1
2
3
>>> text = 'ok!ok!are you ok?'
>>> text.replace('ok!','no!')
'no!no!are you ok?'

字符串格式化

字符串格式化目前有三种方式,分别为占位符(%)、formatf-string

f-string

在Python3.6中,引入了一种新的格式化字符串的方法:f-string。相比占位符和formatf-string更加方便简单。

f-string是指以Ff为前缀的字符串。例如:

1
2
3
4
5
6
>>> length = 30
>>> width = 15
>>> f'矩形的长为{length}cm,宽为{width}cm,面积为{length*width}'
'矩形的长为30cm,宽为15从cm,面积为450'
>>> F'矩形的长为{length}cm,宽为{width}cm,面积为{length*width}'
'矩形的长为30cm,宽为15从cm,面积为450'

3.8版本又引入一个=符号,例如:

1
2
>>> f'矩形{length=}cm,{width=}cm,面积为{length*width}'
'矩形length=30cm,width=15cm,面积为450'

常见问题解决方案

使用多个界定符分割字符串

问题

你需要将一个字符串分割为多个字段,但是分隔符(还有周围的空格)并不是固定的。

解决方案

string 对象的 split() 方法只适应于非常简单的字符串分割情形, 它并不允许有多个分隔符或者是分隔符周围不确定的空格。 当你需要更加灵活的切割字符串的时候,最好使用 re.split() 方法:

1
2
3
4
>>> line = 'asfaf dg;gdg,ddggd,hfhh;gddd gg'
>>> import re
>>> re.split(r'[;,\s]\s*',line)
['asfaf', 'dg', 'gdg', 'ddggd', 'hfhh', 'gddd', 'gg']

知识点补充:re.split()方法

语法格式:

1
2
3
4
5
import re


# maxsplit是分离的次数,maxsplit=1分离一次,默认为0,不限制次数。
re.split(pattern, string, maxsplit=0)

列表

参考:列表的更多特性

Python中没有数组,但是加入了更加强大的列表(list)。

从形式上看,列表会将所有元素都放在一对中括号[]中,相邻元素之间用逗号分隔,元素可以为任何类型,如下所示:

1
[element1,element2,element3,...,elementn]

可以通过type函数查看类型:

1
2
>>> type(['sss',2.34,['sds',11],'ab'])
<class 'list'>

列表的取值

通过下标

列表通过下标来获取列表中的单个值。列表中第一个值的下标是0,第二个值的下标是 1,第三个值的下标是 2,以此类推。例如:

1
2
3
4
5
6
7
8
9
>>> a=[1,2,3,4,'ddd']
>>> a[0]
1
>>> a[4]
'ddd'
>>> a[1.1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list indices must be integers or slices, not float

Tips:下标只能是整数, 不能是浮点值,否则将导致TypeError错误。

列表也可以包含其他列表值。这些列表的列表中的值, 可以通过多重下标来访
问, 像这样:

1
2
3
>>> a=[1,2,[85,'dog'],3,4,'ddd']
>>> a[2][1]
'dog'

虽然下标从0开始并向上增长,但也可以用负整数作为下标。整数值−1指的是
列表中的最后一个下标,−2指的是列表中倒数第二个下标, 以此类推。

1
2
3
>>> a=[1,2,[85,'dog'],3,4,'ddd']
>>> a[-1]
'ddd'

切片

就像下标可以从列表中取得单个值一样,“切片”可以从列表中取得多个值,结果是一个新列表。像下标一样, 但它有两个冒号分隔的整数,第一个数字为切片的起始位置,第二个数字为列表的长度位置,第三个数字为元素的间隔,例如:

1
2
3
4
>>> a[1:5]
[2, [85, 'dog'], 3, 4]
>>> a[1:5:2]
[2, 3]

可以省略切片中冒号两边的一个下标或两个下标。省略第一个下标相当于使用0,或列表的开始。省略第二个下标相当于使用列表的长度,意味着分片直至列表的末尾。例如:

1
2
3
4
5
6
>>> a[:3]
[1, 2, [85, 'dog']]
>>> a[1:]
[2, [85, 'dog'], 3, 4, 'ddd']
>>> a[-2:]
[4, 'ddd']

用len()取得列表的长度

len()函数将返回传递给它的列表中值的个数,就像它能计算字符串中字符的个数一样。在交互式环境中输入以下代码:

1
2
>>> len(a)
6

用下标改变列表中的值

可以使用列表的下标来改变下标处的值。例如:

1
2
3
4
5
>>> a
[1, 2, [85, 'dog'], 3, 4, 'ddd']
>>> a[3]='cat'
>>> a
[1, 2, [85, 'dog'], 'cat', 4, 'ddd']

列表连接和列表复制

+操作符可以连接两个列表,得到一个新列表,就像它将两个字符串合并成一新字符串一样。*操作符可以用于一个列表和一个整数,实现列表的复制。

1
2
3
4
>>> [1,2,3] + ['a','b','c']
[1, 2, 3, 'a', 'b', 'c']
>>> [1,2,3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]

用 del 语句从列表中删除值

del语句将删除列表中下标处的值,表中被删除值后面的所有值,都将向前移动一个下标。

1
2
3
4
>>> a = [1, 2, 3, 'a', 'b', 'c']
>>> del a[2]
>>> a
[1, 2, 'a', 'b', 'c']

in和not in操作符

利用innot in操作符,可以确定一个值否在列表中。像其他操作符一样,innot in用在表达式中,连接两个值:一个要在列表中查找的值, 以及待查找的列表。这些表达式将求值为布尔值。

1
2
3
4
5
>>> a = ['cat','dog','pig']
>>> 'pig' in a
True
>>> 'bird' in a
False

多重赋值

1
2
3
4
5
6
7
8
>>> a = ['cat','dog','pig']
>>> x,y,z=a
>>> x
'cat'
>>> y
'dog'
>>> z
'pig'

但变量数和列表中元素数量不符时,会报ValueError

1
2
3
4
5
>>> a = ['cat','dog','pig','fish']
>>> x,y,z = a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 3)

有时候,你可能只想解压一部分,丢弃其他的值。对于这种情况Python并没有提供特殊的语法。 但是你可以使用任意变量名去占位,到时候丢掉这些变量就行了。

1
2
3
4
5
6
>>> a = ['cat','dog','pig','fish']
>>> _,x,y,_ = a
>>> x
'dog'
>>> y
'pig'

列表的方法

常用方法:增、删、改、查、排序。

查找

列表值有一个index()方法,可以传入一个值,如果该值存在于列表中,就返回它的下标。如果该值不在列表中,Python 就报ValueError

1
2
3
4
5
6
7
>>> a = ['cat','dog','pig']
>>> a.index('dog')
1
>>> a.index('bird')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 'bird' is not in list

增加

方法有:list.append(x)list.insert(i, x)

list.append(x)

在列表的末尾添加一个元素。相当于a[len(a):] = [x]

1
2
3
4
>>> a = ['cat','dog','pig']
>>> a.append('bird')
>>> a
['cat', 'dog', 'pig', 'bird']

list.insert(i, x)

在给定的位置插入一个元素。第一个参数是要插入的元素的索引,所以a.insert(0, x)插入列表头部, a.insert(len(a), x)等同于a.append(x)

1
2
3
>>> a.insert(2,'fish')
>>> a
['cat', 'dog', 'fish', 'pig', 'bird']

删除

remove()方法传入一个值,它将从被调用的列表中删除。

1
2
3
>>> a.remove('cat')
>>> a
['dog', 'fish', 'pig', 'bird']

Tips:如果知道想要删除的值在列表中的下标,del语句就很好用。如果知道想要从列表中删除的值,remove()方法就很好用。

排序

数值的列表或字符串的列表,能用sort()方法排序。

1
2
3
4
>>> a=['cat', 'dog', 'fish', 'pig', 'bird']
>>> a.sort()
>>> a
['bird', 'cat', 'dog', 'fish', 'pig']

需要注意的是

  • sort()方法当场对列表排序。不要写出a = a.sort()这样的代码,试图记录返回值。
  • 不能对既有数字又有字符串值的列表排序,因为 Python不知道如何比较它们,否则会报TypeError 错误。
1
2
3
4
5
>>> a = ['cat',1,3,'fish']
>>> a.sort()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'int' and 'str'
  • sort()方法对字符串排序时,使用“ASCII字符顺序”,而不是实际的字典顺序。这意味着大写字母排在小写字母之前。因此在排序时,小写的a在大写的Z之后。
1
2
3
4
>>> a=['dog','Big','Small','fish']
>>> a.sort()
>>> a
['Big', 'Small', 'dog', 'fish']

列表推导式

列表推导式用于使用其他列表创建一个新列表。

语法格式

如下:

1
2
3
4
5
# 格式1
[表达式 for 变量 in 列表]

# 格式2,对列表进行判断筛选
[表达式 for 变量 in 列表 if 条件]

例子

例1

1
2
3
# 求1-9的平方组成的列表
l = [x**2 for x in range(1, 10)]
print(l)

结果如下:

1
[1, 4, 9, 16, 25, 36, 49, 64, 81]

例2

1
2
3
# 求1-9中偶数的平方组成的列表
l = [x**2 for x in range(1, 10) if x % 2 == 0]
print(l)

结果如下:

1
[4, 16, 36, 64]

常见问题解决方案

删除序列相同元素并保持顺序

问题

怎样在一个列表上面保持元素顺序的同时消除重复的值?

解决

去重可以用not in判断,排序可以用sort方法。

1
2
3
4
5
6
7
def dedupe(items):
seen = []
for item in items:
if item not in seen:
seen.append(item)
seen.sort()
return seen

使用上述函数验证

1
2
3
4
5
6
7
8
9
10
11
12
>>> a = [1515,23,546,77,34,666,23,12,546]
>>> dedupe(a)
[12, 23, 34, 77, 546, 666, 1515]
>>> b = ['dog','pig','cat','fish','bird','pig','fish']
>>> dedupe(b)
['bird', 'cat', 'dog', 'fish', 'pig']
>>> c = ['dog','pig','cat','fish','bird','pig','fish',123]
>>> dedupe(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in dedupe
TypeError: '<' not supported between instances of 'int' and 'str'

Tips:不能对既有数字又有字符串值的列表排序,因为 Python不知道如何比较它们,否则会报TypeError 错误。

找出出现次数最多的元素

问题

怎样找出一个列表中出现次数最多的元素呢?

解决方案

collections.Counter 类就是专门为这类问题而设计的, 它甚至有一个有用的 most_common() 方法直接给了你答案。

1
2
3
4
5
6
7
8
9
10
11
>>> from collections import Counter
>>> animals = [
... 'cat', 'bird', 'dog', 'cat', 'fish', 'dog',
... 'pig', 'pig', 'monkey', 'lion', 'tiger', 'bird',
... 'duck', 'fish', 'monkey', 'bird', 'dog', 'lion',
... 'cat', 'tiger'
... ]
>>> animal_counts = Counter(animals)
>>> top_animal = animal_counts.most_common(1)
>>> top_animal
[('cat', 3)]

过滤列表元素

问题

有一个纯数据的列表,想利用一些规则从中提取出需要的值或者是缩短列表长度。

解决方案

最简单的过滤序列元素的方法就是使用列表推导式。

1
2
3
>>> mylist = [23, 455, 23.5, 98, 21184, 4, -5, 0, 12, -111]
>>> [n for n in mylist if n > 0]
[23, 455, 23.5, 98, 21184, 4, 12]

元组

元组(Tuple)是由一系列按特定顺序排序的元素组成。

与列表(List)的区别

元组与列表类似,不同之处在于元组的元素不能修改。

元组使用小括号,列表使用方括号。

格式

元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。通过( )创建元组后,一般使用=将它赋值给某个变量,具体格式为:

1
tuplename = (element1, element2, ..., elementn)

从存储内容上看,元组可以存储整数、实数、字符串、列表、元组等任何类型的数据,并且在同一个元组中,元素的类型可以不同,例如:

1
info = ('John', '16', ('hh',54))

元组与字符串类似,下标索引从0开始,可以进行截取,组合等。

1
2
3
4
>>> info[2]
('hh', 54)
>>> info[2][1]
54

集合

集合(set)是一个无序不重复元素的序列。

基本功能是进行成员关系测试和删除重复元素

可以使用大括号 { } 或者set()函数创建集合.

Tips:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。

例如:

1
info = {'John', '16', 'boy'}

增删查

查询

1
2
3
>>> info.add('good')
>>> info
{'good', 'boy', 'John', '16'}

copy元素

1
2
3
4
5
6
>>> info1
{'boy', 'John', '16'}
>>> info1 = info.copy()
>>> info1
{'boy', 'John', '16'}
>>>

删除元素

清空元素

1
2
3
>>> info.clear()
>>> info
set()

交集、并集、差集、交叉补集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 交集
s1 = {'123', 'vccc', 'aa', 'bb'}
s2 = {'123', 'dddd', 'bb', '456'}
print(s1.intersection(s2))

# 并集
print(s1.union(s2))

# 差集
>>> s1 - s2
{'vccc', 'aa'}
>>> s2 - s1
{'dddd', '456'}
>>> s1.difference(s2)
{'vccc', 'aa'}
>>> s2.difference(s1)
{'dddd', '456'}

# 交叉补集
>>> s1^s2
{'dddd', 'aa', 'vccc', '456'}
>>> s1.symmetric_difference(s2)
{'dddd', 'aa', 'vccc', '456'}

# 求出差集并更新
>>> s1.difference_update(s2)
>>> s1
{'vccc', 'aa'}

# 判断是否有交集,如果没有交集,返回True
>>> s1.isdisjoint(s2)
False

# 判断是否是子集
>>> s1 = {1, 2, 3}
>>> s2 = {1, 2, 3, 4, 5}
>>> s1.issubset(s1)
True

# 判断是否是父集
>>> s1 = {1, 2, 3}
>>> s2 = {1, 2, 3, 4, 5}
>>> s2.issuperset(s1)
True

# 更新多个值
>>> s1 = {'aaa', 'b'}
>>> s2 = {1, 2, 3}
>>> s1.update(s2)
>>> s2
{1, 2, 3}
>>> s1
{1, 2, 3, 'b', 'aaa'}

字典

像列表一样,字典(dict)是许多值的集合。但不像列表的下标,字典的索引可以使用许多不同数据类型,不只是整数。字典的索引被称为(key),键及其关联的值称为键-值(key-value)对。

语法格式

1
dictname = {'key':'value1', 'key2':'value2', ..., 'keyn':valuen}

例如

1
myCat = {'size': 'fat', 'color': 'gray', 'disposition': 'loud'}

将一个字典赋给myCat变量。这个字典的键是'size''color''disposition'。这些键相应的值是'fat''gray''loud'。可以通过它们的键访问这些值:

1
2
>>> myCat['size']
'fat'

字典仍然可以用整数值作为键, 就像列表使用整数值作为下标一样, 但它们不必从0开始,可以是任何数字。

1
a = {12: 'fish', 523: 'lion'}

字典与列表的区别

不像列表,字典中的表项是不排序的。但字典中没有“第一个”表项。虽然确定两个列表是否相同时,表项的顺序很重要,但在字典中,键-值对输入的顺序并不重要。

1
2
3
4
5
6
7
8
>>> a = ['dog','fish','cat']
>>> b = ['fish','dog','cat']
>>> a == b
False
>>> a={3:'dog',23:'cat',53:'fish'}
>>> b={23:'cat',3:'dog',53:'fish'}
>>> a == b
True

因为字典是不排序的,所以不能像列表那样切片。尝试访问字典中不存在的键,将导致KeyError出错信息。这很像列表的“越界”IndexError出错信息。

1
2
3
4
5
>>> myCat = {'size': 'fat', 'color': 'gray', 'disposition': 'loud'}
>>> myCat['age']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'age'

字典的方法

字典的键、值和键-值对

字典的键、值和键-值对:keys()values()items()
利用keys()values()items()方法,循环分别可以迭代键、值或键-值对。请注意,items()方法返回的dict_items值中,包含的是键和值的元组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> myCat = {'size': 'fat', 'color': 'gray', 'disposition': 'loud'}
>>> for i in myCat.values():
... print(i)
...
fat
gray
loud

>>> for i in myCat.keys():
... print(i)
...
size
color
disposition

>>> for i in myCat.items():
... print(i)
...
('size', 'fat')
('color', 'gray')
('disposition', 'loud')

通过innot in检查某个键或值是否存在于字典中。

1
2
3
4
5
6
7
8
>>> 'name' in myCat.keys()
False
>>> 'size' in myCat.keys()
True
>>> 'gray' in myCat.values()
True
>>> 'gray' not in myCat.values()
False

get()方法

字典有一个get()方法,它有两个参数:要取得其值的键,以及如果该键不存在时,返回的备用值。

1
2
3
4
5
a = {'cat': 2,'dog': 5,'fish': 10}
>>> 'I have ' + str(a.get('fish', 0)) + ' fish.'
'I have 10 fish.'
>>> 'I have ' + str(a.get('bird', 0)) + ' birds.'
'I have 0 birds.'

setdefault()方法

setdefault()方法提供了一种方式,在一行中完成这件事。传递给该方法的第一个参数,是要检查的键。第二个参数,是如果该键不存在时要设置的值。如果该键确实存在,方法就会返回键的值。

1
2
3
4
5
6
7
8
9
 a = {'cat': 2,'dog': 5,'fish': 10}
>>> a.setdefault('bird',3)
3
>>> a
{'cat': 2, 'dog': 5, 'fish': 10, 'bird': 3}
>>> a.setdefault('bird',6)
3
>>> a
{'cat': 2, 'dog': 5, 'fish': 10, 'bird': 3}

常见问题解决方案

字典中的键映射多个值

问题

怎样实现一个键对应多个值的字典?

解决方案

如果你想要一个键映射多个值,那么你就需要将这多个值放到另外的容器中, 比如列表或者集合里面。例如:

1
2
3
4
5
6
7
8
d = {
'a' : [1, 2, 3],
'b' : [4, 5]
}
e = {
'a' : {1, 2, 3},
'b' : {4, 5}
}

选择使用列表还是集合取决于你的实际需求。如果你想保持元素的插入顺序就应该使用列表, 如果想去掉重复元素就使用集合(并且不关心元素的顺序问题)。

字典的运算

问题

怎样在数据字典中执行一些计算操作,比如求最小值、最大值?

以下是蔬菜价格的数据字典:

1
2
3
4
5
6
7
vegetables = {
'tomato': 3.50,
'potato': 2.32,
'cucumber': 1.75,
'eggplant': 5.15,
'pepper': 8.99
}

找出价格最便宜的蔬菜和最贵的蔬菜。

解决方案

如果你在一个字典上执行普通的数学运算,你会发现它们仅仅作用于键,而不是值。比如:

1
2
print(min(vegetables)) # Returns 'cucumber'
print(max(vegetables)) # Returns 'tomato'

使用字典的 values() 方法来解决这个问题:

1
2
3
4
a = min(vegetables.values())
b = max(vegetables.values())
print(f'The lowest price for vegetables is {a}.')
print(f'The highest price for vegetables is {b}.')

输出结果为:

1
2
The lowest price for vegetables is 1.75.
The highest price for vegetables is 8.99.

但不是最终需要得到的结果,最终需要知道最低和最高价格的蔬菜。

zip() 函数方案通过将字典”反转”为 (值,键) 元组序列来解决了上述问题。

1
2
3
4
a = min(zip(vegetables.values(),vegetables.keys()))
b = max(zip(vegetables.values(),vegetables.keys()))
print(f'The lowest price for vegetables is {a}')
print(f'The highest price for vegetables is {b}')

输出结果为:

1
2
The lowest price for vegetables is (1.75, 'cucumber')
The highest price for vegetables is (8.99, 'pepper')