输入:
tup=()
print(tup,type(tup))
得到:
() <class 'tuple'>
添加元素如下:
tup=(1,2,3,4,5)
print(tup,type(tup))
得到:
(1, 2, 3, 4, 5) <class 'tuple'>
tup=(1,2,3,4,5)
print(tup[3])
得到:
4
tup=(1,2,3,4,5)
tup[3]=44
print(tup)
报错:
TypeError: 'tuple' object does not support item assignment
元组是不可变序列,或称不可变对象
tup=10
print(tup,type(tup))
得到:
10 <class 'int'>
此时元组中的数为整型,我们稍加改变:
tup=10,
print(tup,type(tup))
得到:
(10,) <class 'tuple'>
此时就变成了一个元祖。又例如:
tup=1,2,3,4,5
print(tup,type(tup))
输出:
(1, 2, 3, 4, 5) <class 'tuple'>
不加括号,它也是一个元组。因此我们总结如下:
如果元组不是空的,那么它里面至少得有一个逗号
,
tup=10,20,30,40
a,b,c,d=tup
print('a=',a)
print('b=',b)
print('c=',c)
print('d=',d)
得到:
a= 10
b= 20
c= 30
d= 40
感觉似曾相识?回顾这个例子:
a=6
b=8
b,a=a,b
print(a,b)
得到:
8 6
如果我们用两个值解剖四个元素,会出现什么情况呢?
tup=10,20,30,40
a,b=tup
print('a=',a)
print('b=',b)
报错:
ValueError: too many values to unpack (expected 2)
理论上,变量必须和元素一一对应,若不满足,需要加
*
(详见下面的内容)。
该如何调整呢?理论上我们应该再添加两个,但是如果这里缺的值有10000个,我们总不能添加10000个变量吧,因此,我们使用:
tup=10,20,30,40
a,b,*c=tup
print('a=',a)
print('b=',b)
此时:
a= 10
b= 20
我们可以看看此时c是什么效果:
tup=10,20,30,40
a,b,*c=tup
print('a=',a)
print('b=',b)
print('c=',c)
得到:
a= 10
b= 20
c= [30, 40]
说明:剩下的元素以列表的形式全部储存在
c
中,不用考虑变量有多少个。
那么,另一个问题来了,如果想存储中间的元素呢?
tup=10,20,30,40
a,*b,c=tup
print('a=',a)
print('b=',b)
print('c=',c)
得到:
a= 10
b= [20, 30]
c= 40
把第一个给了a
,最后一个给了c
,剩下的中间部分全部给了b
。
同理:
tup=10,20,30,40
*a,b,c=tup
print('a=',a)
print('b=',b)
print('c=',c)
结果可想而知:
a= [10, 20]
b= 30
c= 40
这个功能在列表里是否适用呢?
a,b,*c=[1,2,3,4,5,6,7]
print('a=',a)
print('b=',b)
print('c=',c)
得到:
a= 1
b= 2
c= [3, 4, 5, 6, 7]
也是可以的。字符串呢?
a,b,*c='Python'
print('a=',a)
print('b=',b)
print('c=',c)
得到:
a= P
b= y
c= ['t', 'h', 'o', 'n']
只要是序列,都可以,都是通用的。但若有两个*
号:
a,*b,*c='Python'
print('a=',a)
print('b=',b)
print('c=',c)
报错:
SyntaxError: two starred expressions in assignment
小结:不能同时出现两个及两个以上的
*
号
新的数据结构
,我们称之为‘映射’(mapping)例如,在列表中存了10000个数据,想在其中找到“钢铁侠”,知道索引还好办,不知道就比较麻烦了。
平时的字典查询方法:偏旁部首
Python中的字典:通过唯一名字(页码),快速找到。
key
key
来查询值,值称之为value
,键值对(key-value)
,字典中可以有多个键值对,一项称之为Item
d={}
print(d,type(d))
{} <class 'dict'>
这是个空字典,可以往里面添加元素。语法如下:
{key:value,key:value...}
例如:
d={'name':'葫芦娃','age':'20','sex':'男'}
print(d,type(d))
得到:
{'name': '葫芦娃', 'age': '20', 'sex': '男'} <class 'dict'>
key和value分别可以是哪些值呢?归纳如下:
字典中的值value可以是任意对象,可变不可变均ok
字典的key可以是任意不可变对象(int str bool tuple…)
那key可以重复吗?
d={'name':'葫芦娃','age':20,'sex':'男','name':'钢铁侠'}
print(d,type(d))
得到:
{'name': '钢铁侠', 'age': 20, 'sex': '男'} <class 'dict'>
因此:
字典中的key不能重复,若出现重复,后面的会替代前面的。
若键值较多时,也可以下面的这种书写方式:
headers={
'name':'葫芦娃',
'age':20
}
d={'name':'葫芦娃','age':20,'sex':'男','name':'钢铁侠'}
print(d['name'],d['age'],d['sex'])
得到:
钢铁侠 20 男
参考官网文档
可以使用dict()
函数来创建字典
d=dict(name='葫芦娃',age=18,sex='男')
print(d,type(d))
得到:
{'name': '葫芦娃', 'age': 18, 'sex': '男'} <class 'dict'>
表示向函数中传递3个参数。
或者:
d=dict([('name','葫芦娃'),('age',18)])
print(d,type(d))
得到:
{'name': '葫芦娃', 'age': 18} <class 'dict'>
事实上,这是一个双值子序列。
何为双值子序列呢?
双值序列:序列中有2个值,如 [3,4]
‘mn’
('w',8)
子序列:序列中的元素也是序列,比如列表中套了一个列表。
双值子序列:既是双值序列也是子序列,如[(3,4),(5,6)]
。
len()
函数:获取字典中键值对的个数
d=dict(name='葫芦娃',age=18,sex='男')
print(len(d))
得到:
3
in
:检查字典中是否包含指定的键
not in
:检查字典中是否不包含指定的键
d=dict(name='葫芦娃',age=18,sex='男')
print('name'in d)
print('葫芦娃'in d)
得到:
True
False
我们再输入:
d=dict(name='葫芦娃',age=18,sex='男')
print(d['age'])
得到:
18
但如果这么写:
d=dict(name='葫芦娃',age=18,sex='男')
print(d[age])
将会报错:
NameError: name 'age' is not defined
因此,
在
dict[key]
中,key一定要加引号''
,否则会当成变量来处理。
但如果这么写,把key赋值:
d=dict(name='葫芦娃',age=18,sex='男')
n='name'
print(d[n])
输出:
葫芦娃
此时就不用加引号''
。
当我们输入一个不存在的键:
print(d['n'])
就会报错,程序会终止:
KeyError: 'n'
此时有一种更柔和的方式:
print(d.get('n'))
得到:
None
get()
:get(key[,default])
。default表示非必须,该方法根据字典中的key来获取值,如果你的key不存在,返回None。d=dict(name='葫芦娃',age=18,sex='男')
print(d.get('name'))
得到:
葫芦娃
也可以指定第二个参数,当key值不存在时,会返回默认值。
d=dict(name='葫芦娃',age=18,sex='男')
print(d.get('n','key值不存在'))
得到:
key值不存在
输入:
d=dict(name='葫芦娃',age=18,sex='男')
d['name']='钢铁侠'
print(d)
得到:
{'name': '钢铁侠', 'age': 18, 'sex': '男'}
字典中的k-v被修改。那如果原本就不存在的key值呢?
d=dict(name='葫芦娃',age=18,sex='男')
d['name']='钢铁侠'
d['phone']=['131313']
print(d)
得到:
{'name': '钢铁侠', 'age': 18, 'sex': '男', 'phone': ['131313']}
相当于向字典中添加key-value。
d.setdefault(key,[,default])
:可以向字典中添加k-v输入:
d=dict(name='葫芦娃',age=18,sex='男')
d.setdefault('name','钢铁侠')
print(d)
结果不变:
{'name': '葫芦娃', 'age': 18, 'sex': '男'}
这是为什么呢?
原因:在使用
d.setdefault(key,[,default])
时,如果key
已存在在字典当中,则返回key的值,不会对字典做任何操作;如果key
不存在,则向字典中添加这个key,并设置value。
d=dict(name='葫芦娃',age=18,sex='男')
d.setdefault('name','钢铁侠')
d.setdefault('phone','钢铁侠')
print(d)
得到:
{'name': '葫芦娃', 'age': 18, 'sex': '男', 'phone': '钢铁侠'}
update()
:将其它字典的k-v添加到当前字典中输入:
d1={'a':1,'b':2,'c':3}
d2={'d':4,'e':5,'f':6}
d1.update(d2)
print(d1)
得到:
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}
将d2
字典中的k-v添加至了d1
字典中,那么假如d1
和d2
中有重复的key:
d1={'a':1,'b':2,'c':3}
d2={'d':4,'e':5,'f':6,'a':7}
d1.update(d2)
print(d1)
得到:
{'a': 7, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}
如果有重复的key,后面的value会替换前面的value。
del
:删除字典中的k-v注意语法:
d1={'a':1,'b':2,'c':3}
del d1['a']
del d1['b']
print(d1)
得到:
{'c': 3}
popitem()
:随机删除字典中的一个k-v,一般都会删除最后一个。d1={'a':1,'b':2,'c':3}
d1.popitem()
d1.popitem()
print(d1)
得到:
{'a': 1}
注意,popitem()
是有返回值的,删除之后会将删除后的元素以元组形式返回。
d1={'a':1,'b':2,'c':3}
r=d1.popitem()
print(r)
得到:
('c', 3)
pop('key'[,default])
:根据key来删除字典中的k-vd1={'a':1,'b':2,'c':3}
r=d1.pop('b')
print(r)
print(d1)
得到:
2
{'a': 1, 'c': 3}
会将删除的value返回。
若删除了一个不存在的值:
d1={'a':1,'b':2,'c':3}
r=d1.pop('w','这个key值不存在')
print(r)
print(d1)
得到:
这个key值不存在
{'a': 1, 'b': 2, 'c': 3}
一个小问题:下面这个算复制吗?
d1={'a':1,'b':2,'c':3}
d2=d1
print('d1=',d1)
print('d2=',d2)
答案:不算,
d2
和d1
指向的是同一个对象。拿我们小时候“复制”别人的作业为例,复制完成之后,你们二者的作业压根没什么关系,可能你改了它没改,它改了你没改。
从id()
可以看出,下面这个就是复制了。
d1={'a':1,'b':2,'c':3}
d2=d1.copy()
d1['b']=5000
print('d1=',d1,id(d1))
print('d2=',d2,id(d2))
得到不同的id值:
d1= {'a': 1, 'b': 5000, 'c': 3} 2715805364088
d2= {'a': 1, 'b': 2, 'c': 3} 2715805364160
另一个例子,也是复制:
d1={'a': {'name':'葫芦娃','age':20},'b':2,'c':3}
d2=d1.copy()
print('d1=',d1,id(d1))
print('d2=',d2,id(d2))
得到不同的id值:
d1= {'a': {'name': '葫芦娃', 'age': 20}, 'b': 2, 'c': 3} 1459300806592
d2= {'a': {'name': '葫芦娃', 'age': 20}, 'b': 2, 'c': 3} 1459300856168
下面,到底什么是“浅复制”呢?接着上一个例子:
d1={‘a’: {‘name’:‘葫芦娃’,‘age’:20},‘b’:2,‘c’:3}
d2=d1.copy()
d2[‘a’][‘name’]=‘黑猫警长’
print(‘d1=’,d1,id(d1))
print(‘d2=’,d2,id(d2))
结果:
d1= {'a': {'name': '黑猫警长', 'age': 20}, 'b': 2, 'c': 3} 2009964294080
d2= {'a': {'name': '黑猫警长', 'age': 20}, 'b': 2, 'c': 3} 2009964343656
d2变化了没问题,可为什么d1也会变化呢?不是说修改一个值不会影响另一个值吗?此即浅复制。
浅复制仅仅只会复制字典本身,如果字典中还有个字典,是不会被复制的,因此此时内层并不独立,其中一个改动另一个就随之变化了。
这个值也可以是一个可变对象,这个可变对象也不会被复制。
keys()
:返回字典所有的key例如:
d1={'a': {'name':'葫芦娃','age':20},'b':2,'c':3}
print(d1.keys())
得到key值:
dict_keys(['a', 'b', 'c'])
有了key,我们可以相应的找到value:
d1={'a': {'name':'葫芦娃','age':20},'b':2,'c':3}
for k in d1.keys():
print(d1[k])
得到:
{'name': '葫芦娃', 'age': 20}
2
3
values()
:返回一个序列,序列中保存有字典的值遍历如下:
d1={'a': {'name':'葫芦娃','age':20},'b':2,'c':3}
for v in d1.values():
print(v)
得到:
{'name': '葫芦娃', 'age': 20}
2
3
items()
:返回字典所有的项,k-v双值序列遍历如下:
d1={'a': {'name':'葫芦娃','age':20},'b':2,'c':3}
for k,v in d1.items():
print(k,'=',v)
得到:
a = {'name': '葫芦娃', 'age': 20}
b = 2
c = 3
1)集合只能存储不可变对象
2)集合中存储的对象是无序的
3)集合不能出现重复元素,集合中的元素是唯一的
回顾:
[]
()
{}
那么集合呢?
s={1,2,3,4}
print(s,type(s))
得到:
{1, 2, 3, 4} <class 'set'>
这就是集合创建,那不和字典是一样的嘛?!
注意,若用花括号{}
创建空的内容:
s={}
print(s,type(s))
得到的就是字典:
{} <class 'dict'>
若添加元素,就是一个集合。这一块要区分。
集合不是说无序嘛,我们这样看:
s={6,2,4,1}
print(s,type(s))
得到:
{1, 2, 4, 6} <class 'set'>
因此,元素的插入顺序和最终输出结果不一样。
所谓无序,就是数据保存的顺序和插入顺序不一样。
s=set()
print(s,type(s))
这是一个集合类型:
set() <class 'set'>
添加元素:
s=set(1,2,3)
print(s,type(s))
结果这是不行的:
TypeError: set expected at most 1 arguments, got 3
修改如下,以列表形式添加:
s=set([1,2,3,4,5])
print(s,type(s))
因此,将列表转化为集合,这是可以的:
{1, 2, 3} <class 'set'>
通过set()
将字典转化为集合:
s= set({'a':1,'b':2,'c':3})
print(s,type(s))
得到:
{'a', 'b', 'c'} <class 'set'>
也是可以的,但只会包含key值。
在另一个例子中,我们看看在集合中能否通过索引来找到值,当我们输入:
s={'a','b',1,2,3}
print(s[0])
print(s,type(s))
显示报错:
TypeError: 'set' object does not support indexing
原因在于集合中的元素是无序的,系统无法得知‘0’
对应谁,那在集合中该如何查找呢?
可以做一个类型转化:
s={'a','b',1,2,3}
print(list(s)[0])
得到:
1