python数据类型之【集合、字典】——集合无序,字典在python3.6之后print时好像变为有序,但二者都不支持索引、集合的运算(并集、交集、差集、异或、union( ) )、集合和列表的区别

本文详细介绍了Python中的集合(set)和字典(dict)数据结构,包括创建、添加、删除元素,以及常用方法。集合不保证元素顺序,不允许重复,而字典存储键值对,键唯一。内容涵盖了集合的add、update方法,字典的增删改查操作,以及两者之间的转换和运算。此外,还讨论了集合和字典的区别及其在实际编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意:

 1、集合和字典都没有下标,所以,也就不支持索引下标的相关操作。

2、创建一个空集合比较特殊,有固定写法:set1 = set( ) 

3、列表有序,集合无序;列表内成员可重复,集合内成员不可重复。

4、集合的增加:add( )只能添加一个值,且该值必须是不可变的数据类型(数字、元组、字符串),update( )可以一个或多个值,这些值必须是可迭代的(比如,那5个)。

5、集合的删除:pop( )删除结果中的第一个。remove、discard都是删除指定成员。区别是:如果要删除的成员不在集合里,则remove会报错,而discard不会报错。

一、集合——set

用{ }表示集合。需要注意的是,空集合的定义比较特殊,具体如下:

格式:变量名=set( )

例如:定义一个空集合和非空集合。

set1 = set()  # 创建一个空集合
print(set1)
结果:
set()


set1 = {1, "hello", 4, 6, 3}  #定义一个非空集合
print(set1)

结果:    #因为集合无序,所以结果不唯一
{1, 3, 4, 6, 'hello'}

或{'hello', 1, 3, 4, 6}

或{1, 'hello', 3, 4, 6}
......

1、查看集合所有方法

print(dir(set))
结果:
['__and__', '__class__', '__contains__', '__delattr__', 
'__dir__', '__doc__', '__eq__', '__format__', '__ge__',
 '__getattribute__', '__gt__', '__hash__', '__iand__', 
'__init__', '__init_subclass__', '__ior__', '__isub__',
 '__iter__', '__ixor__', '__le__', '__len__', '__lt__',
 '__ne__', '__new__', '__or__', '__rand__', '__reduce__', 
'__reduce_ex__', '__repr__', '__ror__', '__rsub__',
 '__rxor__', '__setattr__', '__sizeof__', '__str__',
 '__sub__', '__subclasshook__', '__xor__',
 'add', 'clear', 'copy', 'difference', 'difference_update', 
'discard', 'intersection', 'intersection_update',
 'isdisjoint', 'issubset', 'issuperset',
 'pop', 'remove', 'symmetric_difference', 
'symmetric_difference_update', 'union', 'update']

二、集合常用的方法

1、增加——add( )、update( )

集合无序,所有不能使用下标,因此添加进去,位置也是随机的,无法指定,最终打印出来的集合顺序也是多种多样的。需要注意的是,因为集合中的成员是不重复的,所以,如果添加的元素在集合中已存在,那么再添加就没效果。

(1)add(值)——只能添加一个元素,且该元素必须是不可变的数据类型(也叫可哈希数据类型),比如:数值型、元组、字符串。否则报错。

(2update(值)——可以添加一个或者多个元素,但添加的元素必须是可迭代的数据类型,(什么叫可迭代的?能用for循环遍历的就是可迭代,比如:那五个非数值型数据。)——也就是说除了单纯的数字,其它都能添加。但是,数字其实也是可以添加的只要把数字外面裹上[ ]或( )或{ },相当于变相的把数字变成了列表、元组、集合,那么这样也就能添加进去了。

添加进去之后需要注意的是:

(1)如果是字符串,那么结果中就会把字符串进行拆分,比如:

set1 = {"苹果", 2}
set1.update("西瓜")    # 添加一个元素,该元素是一个字符串
print(set1)  
结果:
{'苹果', 2, '瓜', '西'}  

(2)如果是列表、元组、集合,结果就不会拆分。比如:

set1 = {"苹果", 2}
set1.update((99, 456, "hello"))  # 添加一个元素,该元素是一个元组,该元组有3个成员
print(set1)
结果:
{2, 99, 'hello', 456, '苹果'}

(3)如果是字典,结果加的只是键。

set1 = {"苹果", 2}
set1.update({"name": "张三", "age": 18})    # 添加字典,只放键
print(set1)
结果:
{'age', 2, 'name', '苹果'}  

例如:用add添加。

set1 = {"橘子", 3}
set1.add(3.14)      # 添加数值型
print(set1)
结果:
{3.14, '橘子', 3}       # 加什么 出什么



set1 = {"橘子", 3}
set1.add("西瓜")     # 添加字符串
print(set1)
结果:
{'西瓜', 3, '橘子'}



set1 = {"橘子", 3}
set1.add((1,))     # 添加一个元组,只有一个成员
set1.add((8, 9))   # 添加一个元组,有2个成员
print(set1)
结果:
{(8, 9), '橘子', 3, (1,)}


set1 = {"橘子", 3}
set1.add((8, 9), (99,))  # 添加2个元组,即:添加两个元素
print(set1)
结果:                  # 所以,add只能添加一个元素
TypeError: add() takes exactly one argument (2 given)

注意区分添加的是一个元素还是多个元素。例如:

set1.add((8, 9)) —— 一个元组,也就是一个元素,它有2个成员

set1.add((8, 9), (99,))——两个元组,也就是两个元素——所以add会报错

例如:add只能添加不可变的数据类型,比如:数值型、元组、字符串。添加其它就报错。

set1 = {"橘子", 3}
set1.add(["大米"])  # 添加列表
print(set1)

结果:
    set1.add(["大米"])
TypeError: unhashable type: 'list'   



"""
翻译过来就是:不可哈希的类型:列表

什么叫可哈希?
一个对象的哈希值如果在其生命周期内绝不改变,就被称为可哈希。
也就是不可变数据类型,比如:数值型、字符串、元组。

不可哈希:即:可变数据类型,比如:列表、字典、集合。
它们在改变值的同时,却没有改变id,无法由id定位值的唯一性。

"""

#  添加集合也是一样,报错
set1 = {"橘子", 3}
set1.add({"小麦"})
print(set1)
结果:
    set1.add({"小麦"})
TypeError: unhashable type: 'set'

例如:用update添加。

set1 = {"苹果", 2}
set1.update("西瓜")   # 添加了一个元素  (添加的是一个字符串)
print(set1)  
结果:
{'苹果', 2, '瓜', '西'}     # 被拆分


set1 = {"苹果", 2}
set1.update("西瓜", "cd")    # 添加了两个元素 (添加的是2个字符串)
print(set1)
结果:
{2, '瓜', '苹果', '西', 'c', 'd'}


set1 = {"苹果", 2}
set1.update("西瓜", "cd", ["asd", 100])  # 添加多个元素,分别是字符串、列表
print(set1) 
结果:
{'d', 2, 100, 'c', '西', '瓜', '苹果', 'asd'}

# 可以看到,字符串成员被拆分了,而列表成员没被拆分,比如100,没被拆成1,0,0


set1 = {"苹果", 2}
set1.update({99, 100})   # 添加一个元素,集合,也没拆分
print(set1)
结果:
{99, 2, '苹果', 100}

set1 = {"苹果", 2}
set1.update({"name": "张三", "age": 18})  # 添加字典,只放键
print(set1)
结果:
{'age', 2, 'name', '苹果'}  

例如:添加数值型报错。

set1 = {"苹果", 2}
set1.update(99)
print(set1)

结果:
 set1.update(99)
TypeError: 'int' object is not iterable

# 也就是说,数值型是不可迭代对象,也就意味着,update只能添加可迭代对象。
所谓可迭代就是指能用for遍历的对象。比如那5个:列表、元组、字典、集合、字符串。

技巧:把数值型变成列表、元组、集合中的任何一个,就能顺利添加了。

set1 = {"苹果", 2}
set1.update((99,))   # 法1 :把它变成元组  
print(set1)        # !!变成元组时候要注意,如果是单成员,末尾要加逗号
结果:
{'苹果', 2, 99}



set1 = {"苹果", 2}
set1.update({99})    # 法2 :把它变成集合
print(set1)
结果:
{99, 2, '苹果'}


set1 = {"苹果", 2}
set1.update([99])  # 法3 :把它变成列表
print(set1)
结果:
{2, 99, '苹果'}

例如:利用update分别添加一个成员和多个成员。

set1 = {"苹果", 2}
set1.update((99, 456, "hello"))  # 添加一个元素,该元素是一个元组,该元组有3个成员
print(set1)
结果:
{2, 99, 'hello', 456, '苹果'}

set1 = {"苹果", 2}
set1.update((99, 456, "hello"), (1,), [100])  # 添加3个元素,该元素是:2个元组、一个列表
print(set1)

结果:
{1, 2, 99, 100, 456, '苹果', 'hello'}

2、删除——pop( )、remove(值)、discard(值)、clear( )

(1)pop( )——删除结果中的第一个成员,不常用使用pop时候,在删除之前输出一下原集合,可以发现,pop删除的是当前打印出来的第一个元素。

set1 = {1, 5, 2}
print(set1)  # 删除前先打印下set1
set1.pop()  #再用pop删除一个值
print(set1)

结果:
{1, 2, 5}  
{2, 5}   # 可以看见第一个元素被删掉了
  

(2)remove和discard都是删除指定成员。区别是:如果要删除的成员不在集合里,则remove会报错,而discard不会报错。

set1 = {1, 5, 2}
set1.remove(5)   # 5在集合里
print(set1)
结果:
{1, 2}


set1 = {1, 5, 2}
set1.remove(4)    # 4不在集合里,报错
print(set1)
结果:   
KeyError: 4


set1 = {1, 5, 2}
set1.discard(4)     # 4不在集合里,但是不会报错
print(set1)
结果:
{1, 2, 5}


set1 = {1, 5, 2}
set1.discard(5)
print(set1)
结果:
{1, 2}

(3)clear( )——清空集合。

set1 = {1, 5, 2}
set1.clear()
print(set1)

结果:
set()

3、公共方法

set1 = {1, 5, 2}
print(len(set1))
print(max(set1))
print(min(set1))
print(5 in set1)
print(5 not in set1)

结果:
3
5
1
True
False

4、用for 遍历 

遍历出来的结果,可能跟原来定义集合的时候顺序不一样,这是正常的,因为集合无序,所以遍历的时候就没有所谓的顺序可言,但不管怎样,最终结果都是把所有成员都遍历一遍。

set1 = {1, 5, 2}
for i in set1:
    print(i)

结果:
1
2
5

例如:定义一个空集合变量,通过input函数,任意输入3个整数,以此来做为集合的成员,最后求成员中的最大值和最小值,以及遍历该集合。

set1 = set()
a = 0
while a < 3:
    set1.add(int(input("请输入一个数:")))
    a += 1
print("该集合最大值是:%d" % max(set1))
print("该集合最小值是:%d" % min(set1))
for i in set1:
    print(i)

结果:
请输入一个数:-20
请输入一个数:5
请输入一个数:100
该集合最大值是:100
该集合最小值是:-20
100
-20
5

三、集合的运算

主要有:并集、差集、交集、异或(或叫对称差集)。——只适用于集合与集合之间

1、并集—— |   用一个竖杠表示

表示把所有的元素合并到一起组成新的集合,此时,新集合称为这多个集合的并集。

set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
print(set1 | set2)   
结果:
{1, 2, 3, 4, 5, 6}


set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
set3 = {3, 0, 7}
print(set1 | set2 | set3)
结果:
{0, 1, 2, 3, 4, 5, 6, 7}

延申:

集合里还有一个方法,也是求并集——union( ),但与上面不同的是,union不仅可以求集合与集合之间的并集,也可以求集合与可迭代对象之间的并集比如:可以求集合与集合/列表/元组/字典/字符串之间的并集。而只能求集合与集合之间的并集,求集合与其它数据类型之间的并集就会报错。

union( )语法格式:

set1.union(set2, set3...,list1...,tuple1...,dict1...,str1....)

其中,union前面,即set1的位置,必须是一个集合变量union后面就可以随意了,可以是集合、列表、元组、字典、字符串中的一个或多个

例如:

set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
list1 = [90, 100]
tuple1 = (80, 100)
str1 = "加油"
dict1 = {"name": "张三", "age": 18}  # 对于字典,只取键
print(set2.union(set1, list1, tuple1, dict1, str1))
结果:
{1, 2, 3, 4, 5, 6, 100, '油', 'age', 'name', 80, '加', 90}


set1 = {1, 2, 3, 4}
list1 = [90, 100]
print(set1 | list1)
结果:
    print(set1 | list1)
TypeError: unsupported operand type(s) for |: 'set' and 'list'

# 同理,和元组、字典也都会报错。


#如果是数字就报错    所以,union()只适用于集合与可迭代对象之间求并集
set1 = {1, 2, 3, 4}
b = 123
print(set1.union(b))
结果:
    print(set1.union(b))
TypeError: 'int' object is not iterable

2、差集—— - 用减号表示

set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
print(set1 - set2)
结果:
{1, 2}

3、交集—— &   ——取共有部分。

set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
print(set1 & set2)
结果:
{3, 4}

4、异或—— ^  ——取非共有部分

set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
print(set1 ^ set2)
结果:
{1, 2, 5, 6}

四、强制类型转换

例如:将字符串转为集合

a = set("ababc")
print(a)
print(type(a))

结果:
{'a', 'b', 'c'}  或{'c', 'b', 'a'}......
<class 'set'>

需要注意的是:强制转换时,必须是可迭代的对象才能转为集合,否则报错,例如,数值型就不能转。  一般常把字符串强转为集合,其它的比如像列表、元组、字典在编写时候pycharm就会给出友情提示。

a = set(123)   # 数字转为集合——报错 
print(a) 
print(type(a))  # 因为它不是可迭代对象

结果:
    a = set(123)
TypeError: 'int' object is not iterable


a = set("123")   # 字符串“123” 
print(a)
print(type(a))
结果:
{'3', '2', '1'}
<class 'set'>


#列表、元组、字典也能强制转化成集合,但平时不这么写,
#因为在写时候pycharm就会给出提示,让直接写成集合没必要转化。

a = set([123])  或 a = set((123,))  
print(a)
print(type(a))
结果:
{123}
<class 'set'>

a = set({"name": "张三", "age": 18})  # 字典强制转化为集合,只加键
# a = set([123])
print(a)
print(type(a))
结果:
{'age', 'name'}
<class 'set'>

五、集合和列表的区别

1、列表有序,集合无序。

        列表中所有的成员是有序的,对应的就是可以用下标来进行增删改查。而集合中所有成员无序,(也就意味着每次输出时,成员之间的位置不固定),所以就不能使用下标。

2、列表内的成员可重复,集合内的成员不可重复。

        同一个列表中成员的值可以重复,而同一个集合内成员的值不可重复。即:集合里的值都是唯一的。

例如:定义时候,写了多个1多个3,但print时候,也仅会出来一个。即:结果自动去重复。也就是说在print(集合名)的时候会自动删除成员间重复的元素。

set1 = {1, 1, 3, "hello", 4, 6, 3} 
print(set1)   # 定义时候,尽管写了多个1多个3,但print时候,也仅会出来一个
结果:
{1, 'hello', 3, 4, 6}

六、字典——dict

(1)用{ }定义一个字典。

(2)字典用来存放“键值对”的数据,键和值用冒号分隔,多个键值对之间用逗号分隔。

(3)同一个字典内,键不能重复

(4)定义一个空字典:变量名={ }

例如:定义两个字典变量,要求,一个空,一个非空。

dict1 = {}   # 定义一个空字典
print(dict1)
结果:
{}


dict2 = {"name": "张三", "age": 18}   # 定义一个非空字典
print(dict2)  
结果:
{'name': '张三', 'age': 18}

字典和集合的区别:集合里只有值,字典里面是键值对。

七、字典的常用操作——增删改查、公共方法

字典里的所有方法:

print(dir(dict))
结果:
['__class__', '__contains__', '__delattr__',
 '__delitem__', '__dir__', '__doc__', '__eq__',
 '__format__', '__ge__', '__getattribute__',
 '__getitem__', '__gt__', '__hash__', '__init__',
 '__init_subclass__', '__iter__', '__le__', '__len__',
 '__lt__', '__ne__', '__new__', '__reduce__',
 '__reduce_ex__', '__repr__', '__setattr__', 
'__setitem__', '__sizeof__', '__str__', '__subclasshook__', 
'clear', 'copy', 'fromkeys', 'get', 'items', 'keys',
 'pop', 'popitem', 'setdefault', 'update', 'values']

1、增加 或 修改——增加键值对、修改值

语法格式:

(1)字典[键] = 值——如果键存在,那就是修改值,如果键不存在,那就是增加新的键值对。

(2)字典的合并

字典1.update(字典2)——把字典2 加到字典1的后面。如果有相同的键,那么字典1里的值将会被替换。注意:用update()添加的只能是字典,也就是只能添加的是键值对,否则都报错。

dict2 = {"name": "张三", "age": 18}
dict2["name"] = "李四"  # 将name键对应的值"张三" 改为 "李四"
dict2["sex"] = "男"  # 新增一个键值对,键为sex,值为男
print(dict2)

结果:
{'name': '李四', 'age': 18, 'sex': '男'}



# 合并两个字典
dict1 = {"name": "张三", "age": 18}
dict2 = {"sex": "男", "name": "李四"}  # 有相同的键“name”  此时会进行替换
dict1.update(dict2)    # 把字典2的数据,加到字典1的后面
print(dict1) 
结果:
{'name': '李四', 'age': 18, 'sex': '男'}   # 合并后,李四替换了张三

例如:添加的不是键值对,就会报错。

dict1 = {"name": "张三", "age": 18}
list1 = ["hello"]
dict1.update(list1)   # 添加列表,报错
print(dict1)
结果:
    dict1.update(list1)
ValueError: dictionary update sequence element #0 has length 5; 2 is required


dict1 = {"name": "张三", "age": 18}
a = "123"
dict1.update(a)    # 添加字符串,报错
print(dict1)
结果;
    dict1.update(a)
ValueError: dictionary update sequence element #0 has length 1; 2 is required

2、删除——pop( )、popitem( )

格式:

pop("")——根据键,删指定键值对。

popitem( )——删除字典中的最后一个键值对

clear( )——清空字典

例如:删除name键,以及清空字典。

dict2 = {"name": "张三", "age": 18}
dict2.pop("name")  # 删除name键,对应的值也将被删除
print(dict2)
结果:
{'age': 18}


dict2 = {"name": "张三", "age": 18, "sex": "男"}
print(dict2)
dict2.popitem()   # 删最后一个键值对
print(dict2)
结果:
{'name': '张三', 'age': 18, 'sex': '男'}
{'name': '张三', 'age': 18}

dict2 = {"name": "张三", "age": 18}
dict2.clear()    # 清空字典
print(dict2)

结果:
{}

3、查——字典名["键"]、get( )

(1)字典名["键"] 和get( "键")都可以获取键对应的值。——获取某个值

例如:获取name键对应的值。

# 法1
dict2 = {"name": "张三", "age": 18}
a = dict2["name"]   #把键对应的值赋值给变量a
print(a)                
                 # 或者直接写成:print(dict2["name"])
结果:
张三


#法2
dict2 = {"name": "张三", "age": 18}
print(dict2.get("name"))   # 使用get()
结果:
张三

(2)字典名.keys( )——获取所有,结果放到一个列表里。

(3)字典名.values( )——获取所有的,结果也是放到一个列表里。

dict1 = {"name": "张三", "age": 18}
print(dict1.keys())
结果:
dict_keys(['name', 'age'])


dict1 = {"name": "张三", "age": 18}
print(dict1.values())
结果:
dict_values(['张三', 18])

4、for循环遍历字典——for a,b 字典名.items( )

for n in 字典名:——只遍历

for n in 字典名.values():——只遍历

for a, b in 字典名.items():——遍历键值对,将键和值分别赋给两个变量

例如:只遍历键、只遍历值。

dict1 = {"name": "张三", "age": 22}
for n in dict1:
    print(n)   # 只遍历键
结果:
name
age


dict1 = {"name": "张三", "age": 22}
for n in dict1.values():
    print(n)   # 只遍历值
结果:

张三
22

例如:可以通过字典["键"]来获取键对应的值。

dict1 = {"name": "张三", "age": 22}
for n in dict1:
    print(n, dict1[n])  # 字典名[键]可以取键的值

结果:
name 张三
age 22

改进:上面虽然能获取键对应的值了,但毕竟不是在for循环中直接获取的,怎么能直接在for循环中就输出值呢?利用items( )方法来获取字典中的键值对,此时,得到的结果就是一个包含了键和值的元组。

dict1 = {"name": "张三", "age": 22}
for n in dict1.items():  # 利用items()来获取键值对
    print(n)  
结果:
('name', '张三')    # 得到的结果是一个包含了键和值的元组
('age', 22)       # 即:此时n就是一个包含了两个成员的元组,
                   #一个成员是键,一个成员是值

再次改进:将元组进行拆包——去掉括号。

dict1 = {"name": "张三", "age": 22}
for n in dict1.items():
    a, b = n    # 对元组进行拆包
    print(a, b)
结果:
name 张三   # 此时括号没有了
age 22

将代码进行优化:此时,a就是键,b就是键对应的值。

dict1 = {"name": "张三", "age": 22}
for a, b in dict1.items():
    print(a, b)
结果:
name 张三
age 22

例如:求值为22时,对应的键名。

dict1 = {"name": "张三", "age": 22}
for n in dict1:   # 遍历键
    if dict1[n] == 22:   # 字典名[键]--取键的值
        print(n)

结果:
age
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值