Python序列之元组、字典、集合

文章目录

  • 元组
    • 简介
    • 不可修改
    • 访问元素
    • 解包
    • `拓展`
  • 字典
    • 简介
    • 特点
    • 使用
  • 浅复制(拓展)
  • 集合
    • set()
    • 使用
    • 运算
  • 拓展

元组

简介

元组(tuple):
元组是Python中的一中数据结构,也是一个序列,与列表类似,不同的是,元组是不可变的,也就是说,元组中的元素一点定义赋值之后,则无法进行修改

  • 语法
    元组的书写形式:
tuple1 = (1, 2, 3, 4)

不可修改

注意:元组是没有增加、修改、删除的方法的。
Python序列之元组、字典、集合_第1张图片

访问元素

元组访问元素的方式和列表一样,可以通过下标进行访问

tuple1 = (1, 2, 3, 4)   #  tuple1 = 1,2,3,4

print(tuple1[0])  # 1

解包

除了上述之外,元组还可以进行解包:

tuple1 = (1, 2, 3, 4)
a, b, c, d = tuple1
print(a, b, c, d)  # 1 2 3 4

如上代码,多个变量会将元组中的多个元素进行分解赋值,也就是对应位置的元素赋值给对应位置的变量

*思考:
代码中变量个数与元组中的元素个数相同,能够解包赋值,如果不同呢?

  • 变量个数多于元素个数
tuple1 = (1, 2, 3, 4)
a, b, d = tuple1  # ValueError: not enough values to unpack (expected 5, got 4)
print(a, b, d)  # 1 2 3 4
  • 变量个数少于元素个数
tuple1 = (1, 2, 3, 4)
a, b, c = tuple1  # ValueError: too many values to unpack (expected 3)
print(a, b, c)

这样是不是有点鸡肋,如果说我有一百个元素,但是我只是想要其中开始和结束的两个元素,那怎么办?难不成要定义一百个变量?
其实这里支持 * 表示通配:

tuple1 = (1, 2, 3, 4)
a, *b, c = tuple1
print(a, b, c)  # 1 [2, 3] 4

如上:
意思就是说,在这个tuple1元组中,除了第一个和最后一个元素之外的所有元素,都保存在变量b中。
同理,可以这样:

tuple1 = (1, 2, 3, 4)
a, *b = tuple1
print(a, b)  # 1 [2, 3, 4]

或者:

tuple1 = (1, 2, 3, 4)
*a, b = tuple1
print(a, b)  # [1, 2, 3] 4

但是需要注意的是:
在一次解包中,*只能出现一次:


tuple1 = (1, 2, 3, 4)
*a, b, *c = tuple1  # SyntaxError: two starred expressions in assignment
print(a, b, c)  

拓展

解包赋值可以通用到Python中的序列中,如列表,元组、和后面的字典、集合等
不过要注意的是字典解包稍有不同,待会进行演示

字典

简介

字典是另一种可变容器模型,且可存储任意类型对象。
以键-值对的形式进行存储,键值之间用冒号:隔开,多个键值对之间用逗号,隔开,整个字典包括在花括号{}中。

特点

  • 键唯一,值任意
    键在整个字典中都是唯一的,是不会重复的。
    而值可以是任意的数据类型。
    注意:如果添加重复键的值,那么后者会覆盖前面的

  • 查询性能好
    因为字典是通过键-值的形式进行存储,那么只要知道键,则可以直接找到值。所以查询性能比较好。

  • 储存性能相比较差
    而相对的,字典存储的时候就需要键和值对应,所以存储性能相对较差

使用

  • 取值
    字典的值需要通过键来获取,或者修改指定键对应的值
# 根据键取值
d = {"name": "jack", "age": 18, "gender": "男"}
print(d["name"])  # jack

d['name'] = 'tom'
print(d)  # {'name': 'tom', 'age': 18, 'gender': '男'}
  • dict()函数
    该函数可以将包含双值的序列列表或集合转为字典格式
#  dict()
d = dict([('name', 'tom')])
print(d)  # {'name': 'tom'}

d1 = dict([['name', 'tom'], ['age', 18]])
print(d1)  # {'name': 'tom', 'age': 18}

d3 = dict({('name', 'tom')})
print(d3)  # {'name': 'tom'}

d4 = dict({('name', 'tom'), ('age', 18)})
print(d4)  # {'name': 'tom', 'age': 18}

需要注意的是,
1、 必须是双值序列列表或集合。
2、集合中的双值序列只能数元组,不能是列表,如d4

  • len()
    len()函数用来获取字典中的键值对个数,与之前的列表类似

  • in和not in
    关键字in用来判断字典中是否包含指定的键
    not in 则相反,与列表类似。

  • get(key,[默认值])
    get()函数是通过键来获取字典中对应的值并返回

# get(key,默认值)
d = {"name": "jack", "age": 18, "gender": "男"}
res = d.get('name')  # jack
res = d.get('class')  # None
res = d.get('class', '班级')  # 班级

如上代码所示:
如果在字典中,找到了键,则直接返回对应的值
如果没有找到对应的键,则返回None
如果指定了默认值(第二个参数),在没有找到对应结果的时候,返回指定默认值

  • setdefault(key,[default])
# setdefault(key,[default])

d = {"name": "jack", "age": 18, "gender": "男"}
d.setdefault('class')
print(d)  # {'name': 'jack', 'age': 18, 'gender': '男', 'class': None}

d = {"name": "jack", "age": 18, "gender": "男"}
d.setdefault('class', 2)
print(d)  # {'name': 'jack', 'age': 18, 'gender': '男', 'class': 2}

d = {"name": "jack", "age": 18, "gender": "男"}
d.setdefault('age', 12)
print(d)  # {'name': 'jack', 'age': 18, 'gender': '男'}

根据代码演示:
setdefault()函数可以向字典中添加键值对
需要注意的是:
1、如果不指定默认值,则添加指定的键,对应的值为None,否则值为指定的值
2、如果添加的键已经存在字典中,则不会对字典产生影响

  • update()
    update()函数是将其他字典添的键值对加到指定字典中
# update()
d = {"name": "jack", "age": 18, "gender": "男"}
d2 = {"class": 2, "grade": "三"}
d.update(d2)
print(d)  # {'name': 'jack', 'age': 18, 'gender': '男', 'class': 2, 'grade': '三'}
  • del
    关键字del用来删除指定的键值对
# del
d = {"name": "jack", "age": 18, "gender": "男"}
del d['age']
print(d)  # {'name': 'jack', 'gender': '男'}
  • popitem()
    该函数会随机删除一个键值对,一般会删除最后一个
# popitem()
d = {"name": "jack", "age": 18, "gender": "男"}
d.popitem()
print(d)  # {'name': 'jack', 'age': 18}
  • pop
# pop(key[,默认值])
d = {"name": "jack", "age": 18, "gender": "男"}
res = d.pop('name')
print(res)  # jack
print(d)  # {'age': 18, 'gender': '男'}

d = {"name": "jack", "age": 18, "gender": "男"}
# res = d.pop('class') # KeyError: 'class'
res = d.pop('class', '指定值不存在')
print(res)  # 指定值不存在
print(d)  # {'name': 'jack', 'age': 18, 'gender': '男'}
  • copy()
# copy()
d = {"name": "jack", "age": 18, "gender": "男"}

d2 = d.copy()
print(d)  # {'name': 'jack', 'age': 18, 'gender': '男'}
print(d2)  # {'name': 'jack', 'age': 18, 'gender': '男'}

d2['name'] = 'tom'
print(d)  # {'name': 'jack', 'age': 18, 'gender': '男'}
print(d2)  # {'name': 'tom', 'age': 18, 'gender': '男'}

copy()函数,会将字典复制一份。并且两个字典完全独立,也就是修改其中一份不会影响另一份

  • clear()
    清除字典,即将字典中的键值对全部清除,没什么好解释的

  • 遍历字典
    思考:我们遍历字典,要遍历的一般是值,
    思考:我们如何获得值

  • 获得所有的键,通过遍历键来遍历值

# keys()
d = {"name": "jack", "age": 18, "gender": "男"}
print(d.keys())  # dict_keys(['name', 'age', 'gender'])

for k in d.keys():
    print(d[k])
    
# jack
# 18
# 男
  • 获得所有的值,直接遍历值
d = {"name": "jack", "age": 18, "gender": "男"}
print(d.values())  # dict_values(['jack', 18, '男'])

for v in d.values():
    print(v)

# jack
# 18
# 男
  • 获得所有的键值对,直接遍历键和值

d = {"name": "jack", "age": 18, "gender": "男"}
print(d.items())  # dict_items([('name', 'jack'), ('age', 18), ('gender', '男')])

for item in d.items():
    print(item)

# ('name', 'jack')
# ('age', 18)
# ('gender', '男')

# 通过之前说的解包改变代码

for k, v in d.items():
    print(k, v)

# name jack
# age 18
# gender 男

浅复制(拓展)

字典的使用内容中说了copy()复制。说复制出来的两份字典互不影响,改变其中一个则另一个不会改变。
现在来看这一段代码

d = {'name': 'jack', 'friend': {'name': 'tom', 'age': 17}, 'age': 18}
d1 = d.copy()
print(d)  # {'name': 'jack', 'friend': {'name': 'tom', 'age': 17}, 'age': 18}
print(d)  # {'name': 'jack', 'friend': {'name': 'tom', 'age': 17}, 'age': 18}

# 这里改变其中项:friend:{'name': 'tom', 'age': 17}
d1['friend']['name'] = 'lucy'
print(d)  # {'name': 'jack', 'friend': {'name': 'lucy', 'age': 17}, 'age': 18}
print(d1)  # {'name': 'jack', 'friend': {'name': 'lucy', 'age': 17}, 'age': 18}

咦?不是说改变其中一个字典,不会影响另一份吗?怎么这里进行修改,另一份也跟着变了

这是因为copy()函数是进行浅复制。也就是浅层次的复制。
它只对d这个字典进行了复制,而d中的某一个项引用的又是另一个对象,但是此时的复制也只是将这一个项保存的引用地址复制了一份,并没有将指向的对象也复制一份。
所以导致d中的friend和d1中的friend指向的都是同一个地方,其中一个改变,另一个也会跟着改变

集合

集合:set,
集合是多个元素放在一队对花括号{}中,元素之间用逗号,隔开
如:

s = {1, 2, 3, 4}
print(s)  # {1, 2, 3, 4}

集合与列表十分相似,但也有以下不同点:

  • 集合中只能存储不可变对象
  • 集合中存储的对象是无序的
  • 集合中不能出现重复的元素
  • 可变对象,可以新增、删除、修改其中的元素

1、只能存储不可变对象

s = {'123', 'h', '就'}
print(s)  # {'123', '就', 'h'}

s1 = {(1, 2, 3), (4, 5, 6)}
print(s1)  # {(4, 5, 6), (1, 2, 3)}

s2 = {[1, 2, 3], [4, 5, 6]}
print(s2)  # TypeError: unhashable type: 'list'

2、无序的

s = {20, 10, 1, 2, 3, 4}
print(s)  # {1, 2, 3, 4, 10, 20}

3、不重复

s = {20, 10, 1, 2, 3, 4, 20, 10, 1, 2, 3, 4}
print(s)  # {1, 2, 3, 4, 10, 20}

set()

set()函数可以用来创建集合,或者将序列和字典转为集合

s = set()
print(s)  # set()

t = (1, 2, 3)
s = set(t)
print(s)  # {1, 2, 3}

l = [1, 2, 3]
s = set(l)
print(s)  # {1, 2, 3}

d = {"name": "jack", "age": 18, "gender": "男"}
s = set(d)
print(s)  # {'name', 'age', 'gender'}

注意:set()函数只能将字典的键转为集合

使用

  • in 、 not in 和len()、update()、remove()、clear()
    这三个用法与之前的一样,不做解释

  • add()
    向集合中添加元素

s = {1, 2, 3}
s.add(4)
print(s)  # {1, 2, 3, 4}

运算


s1 = {1, 2, 3, 4, 5}
s2 = {3, 4, 5, 6, 7}

# 交集运算 &
# 两个集合中重复的元素
r = s1 & s2
print(r)  # {3, 4, 5}

# 并集运算 |
# 两个集合进行合并
r = s1 | s2
print(r)  # {1, 2, 3, 4, 5, 6, 7}

# 差集运算 -
# 前者集合有哪些元素不在后者集合中
r = s1 - s2
print(r)  # {1, 2}

r = s2 - s1
print(r)  # {6, 7}

# 异或集运算 ^
# 集合里面不相交的部分
r = s1 ^ s2
print(r)  # {1, 2, 6, 7}
# print('s1 =',s1)
# print('s2 =',s2)
# print('r =',r)

# 返回的是布尔类型
# <= 检查一个集合是否是另一个集合的子集
# < 检查一个集合是否是另一个集合的真子集
# >=检查一个集合是否是另一个集合的超集
# >检查一个集合是否是另一个集合的真超集

a = {1, 2, 3}
b = {1, 2, 3, 4, 5}
c = {1, 2, 3, 4, 5}

print(a <= c)  # True
print(a < c)  # True
print(b <= c)  # True
print(b < c)  # False

拓展

可变对象与不可变对象

# 可变对象
# 可变对象,也就是说,改变对象中的其中一个值,变量所保存的对象并不会改变,依旧是原来的那个对象


# 不可变对象
# 与可比那对象相反,如果改变对象中的某一个值,那么对象就不是原来的对象
a = '123'
b = a
print(a, id(a))  # 123 2001426837944
print(b, id(b))  # 123 2001426837944
b = '124'
print(a, id(a))  # 123 2001426837944
print(b, id(b))  # 123 2001427673248

a = [1, 2, 3]
b = a
print(a, id(a))  # [1, 2, 3] 2001427667976
print(b, id(b))  # [1, 2, 3] 2001427667976
b[0] = 10
print(a, id(a))  # [10, 2, 3] 2001427667976
print(b, id(b))  # [10, 2, 3] 2001427667976

通过以上代码示例:
能够发现,当有两个对象同时指向一个值的时候(b=a)
在都没发生变化的时候,发现两个对象的id是一样的

  • 但是其中一个发生了变化,如果另一个没有发生变化,另外一个值不会发生变化,那么这个对象就是不可变对象,因为不可变特质,所以一旦改变,就等于是新生成一个对象重新赋值,id也会跟着改变,那么与之前的那个对象就没有任何关系,所以之前的对象没有跟着改变
  • 而可变对象则是相反,其中一个对象的值发生变化,则另一个对象的值跟着变化,并且id不变

你可能感兴趣的:(Python)