python代码学习——列表、字典及元组、ipython

  • 数据类型总结:
  • 可变类型:list、dict、set
  • 不可变类型:bool、str、int、float、tuple、None
  • 数据类型的转换:int(),str(),float(),set()
    • 转换int,数字字符串,float可以转换为int
    • 转换str,所有的数据类型都可以转换,
    • 转换float:int,或者整数或者小数字符串可以转换为float
    • 转换list:元组转换列表
  • 有序:str、list、tuple
  • 无序:dict、set
  • 可迭代:str、list、dict、tuple、set、range
  • 不可迭代:int、float、bool

一、列表

列表的定义、格式及特点

列表:由一系列按照特定顺序排列元素组成的集合
格式:[元素a,元素b]
列表的定义:赋值即定义,列表不能一开始就定义大小
关键字:list,注意:list不能用于命名
特点:

  • 可修改有序的,可变的
  • 存在空列表
  • 元素之间使用逗号隔开,使用[]括起来
  • 什么元素都可已放进列表,整数,浮点数,;列表,元组,字符串,布尔值都可以
  • 线性的数据结构

以下是列表的代码及输出运行结果

list_msg=[100,112.45,
'python','java',
{'dict_key':'dict_value'},
[2,5,'hdjhiaf'],
(78,'hajhjfa','C#')]
print(list_msg)

在这里插入图片描述

列表,链表,stack和queue的区别

  • 列表时有序、可变的线性结构,可预知下一个元素偏移几个单位
  • 链表是有序的非线性结构,零散放置,不能使用偏移的方式寻找,即不可使用索引的方式寻找
  • queue,队列,有序的自定义结构方式,可线型也可非线型;先进先出,后进先出,可以从两头走
  • stack 栈,后进先出,竖着放置,从上往下取值,先进的在底部,后进的在最上面,取值从最上面取

列表的取值、切片、嵌套取值

直接使用索引取值

  • 列表的取值格式:列表名[索引值]
  • 列表是有序的,因此列表的取值可根据列表的下标(索引值)来获取,列表的下标从0开始
  • 列表的切片:列表名[元素头的位置:元素尾的位置+1:步长],与字符串的切片类似,其默认步长为1
list_msg=[100,112.45,'python','java',
{'dict_key':'dict_value'},[2,5,'hdjhiaf'],
(78,'hajhjfa','C#')]
a=list_msg[4]
print("列表中索引为4的值为:",a)
b=list_msg[2:5:1]#存在步长
c=list_msg[2:5]#不取步长
d=list_msg[2:6:2]#步长为2
print("列表中第2-4个元素",b)
print("列表中第2-5个元素,默认步长取值:",c)
print("列表中第2和第4个元素:",d)

在这里插入图片描述
4.列表的嵌套取值,思考:如以下代码,如何取值404?

list_int=[100,[102,105,107],200,[205,209,[303,404]]]

列表的嵌套取值方法: 在索引值后面直接加上嵌套元素的下标即可,取值方式代码及运行结果如下:

list_int=[100,[102,105,107],200,[205,209,[303,404]]]
list_value=list_int[3][2][1]
print(list_value)

在这里插入图片描述

使用函数查找

index、count和len

1.index(value)

  • 通过value,从指定区间查找列表中的元素是否匹配
  • 如果匹配到第一个元素就立即返回索引
  • 如果匹配不到,抛出异常ValueError
  • 可以在value后加索引,查找的是指定索引之后的数值,返回的是从左至右的索引值

2.count(count)

  • 返回列表中匹配value的次数

3.index和count的时间复杂度

  • index和count方法的时间复杂度都是O(n)
  • 随着列表数据规模的增大,效率会下降

4.len(列表名)

  • 返回列表的长度
  • 代码示例:
list_msg=['i love python','java','web',
          'ios',3,78,9,32,'yezi','love','java',78]
print("count,统计value的个数:",list_msg.count('java'))
print("index,从左至右取值:",list_msg.index(78,1))
print("index,从右至左取值:",list_msg.index(78,-2))
print("index,默认:",list_msg.index(78))
print("len,列表长度:",len(list_msg))

在这里插入图片描述

列表元素的增删改

列表元素的修改

  • 格式:列表名[索引值]=value(要更新的值)
  • 注意:索引不要越界
  • 代码示例:
list_msg=['i love python','java','web',
          'ios',3,78,9,32,'yezi','love','java',78]
list_msg[-1]="haha"

在这里插入图片描述

列表元素添加(append、instert、+、*、extend)

列表元素的添加有5种方式,分别为append、instert、+、*和extend
1.列表名.append(添加值)

  • 列表尾部追加,返回值为None
  • 返回None意味着不能使用变量接收,在原列表中进行修改
  • 其时间复杂度是O(1),因为有固定索引,不需要改变列表的其他元素

2.列表名.insert(索引,添加值)

  • 在指定的索引(index)中插入元素,返回值也是None
  • 返回None意味着不能使用变量接收,在原列表中进行修改
  • 时间复杂度不确定,如果索引为-1,其时间复杂度为O(1),如果在中间插入元素,需要修改添加索引之后的元素的内存排序,会消耗一定的效率
  • 当索引超越上界时,在尾部追加;索引超越下界时,在头部追加

3.列表名.extend(iteratable)

  • iteratable指的是可迭代的对象,将其追加进来,返回值为None
  • 返回None意味着不能使用变量接收,在原列表中进行修改
  • 可迭代的对象,可以是列表,可以是字典,可以是字符串,可以是元组
  • 可迭代的元素,如果是字典,默认迭代字典的key值,value值可以使用字典.values()添加

4.列表+列表

  • 两个列表的拼接
  • 有返回值,可用变量接收

5.列表*数值

  • 重复操作,将列表中的元素重复n次
  • 有返回值,可用变量接收

6.代码示例:

list_1,list_2=[1,2,3,4,5],[1,2,3]
a=list_1+list_2
print("列表1和列表2拼接,+",a)
b=list_2*3
print("列表2重复3次",b)
list_1.append(6)
print("列表1末尾追加6",list_1)
list_2.insert(1,7)
print("列表2在第一个索引上插入7:",list_2)
list_1.insert(100,10)
print("列表1超越上届插入:",list_1)
list_2.insert(-100,50)
print("列表2超越下界插入:",list_2)
list_1.extend(list_2)
print("列表1和列表2拼接,extend",list_1)

list_1 = [1,2,3]
dict_1 = {"name":2}
str_1 = "app"
tuple_1 = (1,2,3)
list_1.extend(dict_1)#添加字典key
list_1.extend(dict_1.values())#添加字典values
list_1.extend(dict_1.items())#添加字典的所有元素,样式为元组
list_1.extend(str_1)
list_1.extend(tuple_1)
print(list_1)

========运行结果==============
列表1和列表2拼接,+ [1, 2, 3, 4, 5, 1, 2, 3]
列表2重复3[1, 2, 3, 1, 2, 3, 1, 2, 3]
列表1末尾追加6 [1, 2, 3, 4, 5, 6]
列表2在第一个索引上插入7: [1, 7, 2, 3]
列表1超越上届插入: [1, 2, 3, 4, 5, 6, 10]
列表2超越下界插入: [50, 1, 7, 2, 3]
列表1和列表2拼接,extend [1, 2, 3, 4, 5, 6, 10, 50, 1, 7, 2, 3]

[1, 2, 3, 'name', 2, ('name', 2), 'a', 'p', 'p', 1, 2, 3]

列表元素的删除和清空(remove、pop、clear、del)

列表元素的删除有5种方式,分别为remove、pop、clear、del
1.列表名.remove(列表元素)

  • 从左至右删除第一个匹配到元素列表的值,移除该元素后,返回None
  • 返回None意味着不能使用变量接收,在原列表中进行修改
  • 移除元素后,其他的元素要进行补位,会引起比较大的效率问题,因此尽可能的少用

2.列表名.pop()

  • 不指定索引index,就从列表尾部弹出一个元素
  • 指定索引,就从索引出弹出一个元素,索引超界抛出IndexError的错误
  • 删除元素后**,返回被删除的元素,可使用变量接收后进行下一步操作**
  • 不指定索引,时间复杂度为O(1),指定索引后,相当于remove,时间复杂度较高

3.列表名.clear()

  • 清空列表中的所有元素,剩下一个空列表
  • 清空元素过多,且没有对元素元素进行再处理的情况下,易引起垃圾回收,会带来一定的效率问题

4.del 列表名[索引]

  • 没有索引的情况下,删除的是整个列表
  • 存在索引的情况下,删除的是指定索引的值
  • 可使用切片删除列表中的值

代码及运行结果如下:

list_1,list_2=[1,2,3,4,5],[1,2,3]
list_2.remove(1)
print("remove删除某个元素后的列表:",list_2)
a=list_1.pop()
print("pop删除最后一个元素:",a,"列表:",list_1)
b=list_1.pop(2)
print("pop删除第二个索引的元素:",b,"列表:",list_1)
list_2.clear()
print("清空列表:",list_2)
del list_1[2:]
print("del删除第二个索引之后的元素",list_1)
del list_2
print(list_2) #列表已经删除,再次打印时报错
=================run result===========
Traceback (most recent call last):
  File "/Users/practice_3.py", line 157, in <module>
    print(list_2)
NameError: name 'list_2' is not defined. Did you mean: 'list_1'?
remove删除某个元素后的列表: [2, 3]
pop删除最后一个元素: 5 列表: [1, 2, 3, 4]
pop删除第二个索引的元素: 3 列表: [1, 2, 4]
清空列表: []
del删除第二个索引之后的元素 [1, 2]

排序和反转

1.列表名.sort(key=None,reverse=false)

  • 对列表中的元素进行排序,就地修改,默认升序
  • 当reverse为True,表降序排列
  • key参数可传一个函数,按照key的指定排序

2.列表名.reverse()

  • 将列表元素反转,本末倒置,返回值为None
  • 返回None意味着不能使用变量接收,在原列表中进行修改

3.代码示例:

list_1=[88,44,66,99,101,29,4,6]
list_1.sort()
print("默认排序:",list_1)
list_1.sort(reverse=True)
print("定义降序:",list_1)
list_1.append("java")
print("列表追加字符串:",list_1)
list_1.sort(key=str,reverse=True)
print("key指定排序:",list_1)

在这里插入图片描述

函数:enumerate

  • 返回可迭代对象的索引及元素信息
  • 返回信息为二元组,可使用for循环读取
m = "djhfi"
n=["2",6,"fjgk",4,66]
for i,value in enumerate(m):
    print(i,value)
for i,value in enumerate(n):
    print(i,value)

+++++++++++++++++++执行结果+++++++++++++++++++++++
0 d
1 j
2 h
3 f
4 i
0 2
1 6
2 fjgk
3 4
4 66

列表的复制

详见《列表复制和copy》

列表例题——杨辉三角的进化

在这里插入图片描述

方式一:

  • 直接定义空列表
  • 使用双层for循环遍历追加元素
  • 没有一次性开辟空间,不清楚需要多大的空间,空间复杂度比较高
  • 先确定嵌套列表的值,然后讲起追加到外层列表中
list_data = []
n = 6
flag = False
for i in range(n):
    cur = [1]
    list_data.append(cur)
    if i==0:
        continue
    for j in range(i-1):#i=1时进不来
        cur.append(list_data[i-1][j-1]+list_data[i-1][j])
    cur.append(1)
print(list_data)

方式二:

  • 先定义空列表,使用for循环先确定列表所需的空间
  • 然后对嵌套列表的前后同时赋值,循环次数少了一半
list_data = []
n = 6
for i in range(n):
    cur = [1]
    for j in range(i):#先确定列表所需的空间,最终的结果为:[[1],[1,1],[1,0,1]……]
        cur.append(1) if j == i-1 else cur.append(0)
    list_data.append(cur)
    if i==0:
        continue
    for x in range(1,i//2+1):#整除,只循环列表长度的一半
        data = list_data[i-1][x-1]+list_data[i-1][x]
        cur[x]=data#对列表的首赋值
        if x!=i-x:#如果是奇数,跳过
            cur[-x-1]=data#使用列表取值的倒序的情况,对列表的对称尾部赋值
print(list_data)

方式三:

  • 相比方法二,少了一个for循环,直接使用乘法确定嵌套列表所需的空间
  • 对嵌套列表的处理方式不变
list_data =[]
n=6
for i in range(n):
    cur = [1]*(i+1)
    list_data.append(cur)
    if i==0:
        continue
    for j in range(1,i//2+1):
        data = list_data[i-1][j-1]+list_data[i-1][j]
        cur[j]=data
        if j!=i-j:
            cur[-j-1]=data
print(list_data)

例题2——杨辉三角的变种

  • 求杨辉三角的第m行,第k个元素
    【思路】直接判断最外面的行,然后最外行大于自己的行数时,跳出循环
x=4
y=3
n=6
list_data =[]
for i in range(n):
    if i > x:
        break
    cur = [1]*(i+1)
    list_data.append(cur)
    if i==0:
        continue
    for j in range(1,i//2+1):
        data = list_data[i-1][j]+list_data[i-1][j-1]
        cur[j]=data
        if i!=2j:
            cur[-j-1]=data

print(list_data)
print(list_data[x-1])
print(list_data[x-1][y])
  • 方法二:对输入的行数和杨辉三角的总行数进行判断,然后先确认前一行,再使用前一行推断后一行,代码如下:
pre = [1]
cur = [1]
m=6
k=5
if k<m:
    for i in range(1,m-1):
        pre.append(0)#,pre,前一行,后面会进行交换
        cur.append(1)#cur,后一行,最终确定下来的行
        if i !=1:
            for j in range(1,i//2+1):
                cur[j]=pre[j-1]+pre[j]
                if 2*j !=1:
                    cur[-j-1] = cur[j]
        cur,pre = pre,cur#因为cur是确定下来的行,为了在for循环中推算下一行的数据,交换
    print("第{}行,第{}列的数据是{}".format(m,k,pre[k-2]+pre[k-1]))
elif m==k or k==1:
    print("第{}行,第{}列的数据是1".format(m,k))
else:
    print("k行大于杨辉三角的行数")
  • 方法三:使用杨辉三角的公式进行计算:C(n,r) = n!/(r! * (n-r)!)
m=9
k=8
#C(n,r) = n!/(r! * (n-r)!)
n = m-1
r = k-1
d = n-r

targ_list = []#放置n,r,k三个值
factorial =1
for i in range(1,n+1):
    factorial *= i#1*2*3*4  阶乘
    if i == r:
        targ_list.append(factorial)#k-1的结成
    if i == d:
        targ_list.append(factorial)#n-r的阶乘
    if i == n:
        targ_list.append(factorial)#m-1的阶乘
print(targ_list[2]//targ_list[1]*targ_list[0])

例题3——转置矩阵

题目:将以下矩阵转置打印

123 147
456 ---- 258
789 369

思路:对角线不动,a[i][j] = a[j][i],而且到了对角线就停止去做下一行,对角线上的元素不动

list_data = [[1,2,3],[4,5,6],[7,8,9]]
for i ,row in enumerate(list_data):
    for j,rol in enumerate(row):
        if i<j:
            list_data[i][j] ,list_data[j][i] = list_data[j][i] ,list_data[i][j]
print(list_data)
+++++++++++++++++++++++++++++执行结果+++++++++++++++++++
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

题目:将以下矩阵转置打印

123 14
456 ---- 25
36

  • 方法一L:直接追加,小规模矩阵,这种方式的效率比一次性开辟空间的效率高;但大规模矩阵,这种方式的效率比一次性开辟空间要低
list_data = [[1,2,3],[4,5,6]]
tm = []
for row in list_data:
    for i , col in enumerate(row):
        # i的值为[1,2,3]或者[4,5,6]的索引,只能是0,1,2
        if len(tm)<i+1:
            # 当tm中元素个数小于3的时候,会添加空列表,大于等于不添加
            tm.append([])

        tm[i].append(col)
print(list_data)
print(tm)

=====================执行结果========================
[[1, 2, 3], [4, 5, 6]]
[[1, 4], [2, 5], [3, 6]]
  • 方法二:一次性开辟好目标矩阵的内存空间,然后原矩阵的元素直接移动到转置矩阵的对称坐标即可
  • 在原有矩阵是做改动,牵扯到增加元素或者减少元素,因此定义一个新的矩阵输出
#方式一:解析式
list_data = [[1,2,3],[4,5,6]]
tm = [[0 for col in range(len(list_data))] for row in range(len(list_data[0]))]

for i ,row in enumerate(tm):
    for j,rol in enumerate(row):

        tm[i][j] = list_data[j][i]

print(tm)

#方式二:for循环开辟空间
list_data = [[1,2,3],[4,5,6]]
tm = [0]*len(list_data[0])
for x in range(len(tm)):
    tm[x] = [0]*len(list_data)

for i ,row in enumerate(tm):
    for j,rol in enumerate(row):

        tm[i][j] = list_data[j][i]

print(tm)
======================执行结果================================
[[1, 4], [2, 5], [3, 6]]
[[1, 4], [2, 5], [3, 6]]

例题4——统计随机数的重复次数

  • 随机产生1-20以内的10个数
  • 统计重复出现的数字,分别是什么
  • 统计不重复的数字,分别是什么
import random

#方法一:将随机数中的数值放在列表中记录次数,然后打印
print("**********type_1***************")
nums = []
for _ in range(10):
    nums.append(random.randrange(21))
print(nums)

num_count = [0]*21
for item in nums:
    num_count[item] +=1

for index in range(len(num_count)):
    if num_count[index] == 0 :
        continue
    elif num_count[index] >1:
        print("{} repeat {} items".format(index,num_count[index]))
    elif num_count[index] ==1:
        print("{} repeat only one".format(index))


#方式二:写一个标记记录布尔值,使用另外一个列表记录数据是否重复,如果重复,元素变为1,循环到次continue,布尔值为正
print("**********type_2***************")
len_num = len(nums)
samenums = []
diffnums = []
states = [0]*len_num

for i in range(len_num):
    flag = False
    if states[i]==1:
        continue
    for j in range(i+1,len_num):
        if states[i] ==1:
            continue
        if nums[i] == nums[j]:
            flag=True
            states[j]=1
    if flag:
        samenums.append(nums[i])
        states[i]=1
    else:
        diffnums.append(nums[i])

print(samenums)
print(diffnums)

二、元组

1.元组的关键字,特点

元组的关键字:tuple,有以下特点:

  • 由()括起来的集合,一个有序的元素组成的集合
  • 有序不可变
  • 可存在空的元组
  • 如果元组中只有一个数据,请加一个逗号,否则会变成非元组
  • 什么类型的数据都可以放 整数,浮点数,字符串,元组都可以
  • 取单个元组 元组名[索引值] 索引从0开始,去下标即可
  • 元组中,元素之间都使用逗号隔开
  • 重点:元组中的元素不能进行修改,即元组不支持增删改
    在这里插入图片描述

元组的初始化

t=()
t=tuple(range(1,7))
t1=(1,2,3,4,5,6,7)
t2=(1,)*5
t3=(1,2,3)*6
t4 = 2,3
t = 3,2

在这里插入图片描述

元组的切片、嵌套取值

元组的访问,切片和嵌套取值格式与列表一致,可参考列表,代码及运行结果如下所示:

  • 支持正负索引,正索引从0开始;负索引从-1开始
  • 如果元组中嵌套列表或者字典,对于嵌套列表或字典中的元素,是可以改变的
  • 正索引不可以越界,否则会报错
  • 相比列表的好处:他比列表占用的内存空间少
  • 取值方式:tuple[索引值]
tuple_int=(1.43,[4,6,7],{"dict_key":"dict_value"},
("dkqakdf",1.5),"fskfgv")
print("取值",tuple_int[3])#取值
print("切片,不输入数值",tuple_int[::2])#切片,不输入数值,默认正无穷和负无穷
print("切片,无步长",tuple_int[2:4])#切片,无步长
print("嵌套取值",tuple_int[-2][1])#嵌套取值
print("原元组:",tuple_int)
tuple_int[1][1]=5
print("修改后的元组:",tuple_int)

在这里插入图片描述

元组的函数

  • 统计函数 元组名.count(value);有返回值,可用变量接收;找到第一个元素就返回,没有找到会抛出异常:ValueError
    • 返回列表中匹配value的次数
  • 索引函数 元组名.index(value,start,stop);有返回值,可用变量接收;返回的是集合中匹配到元素的个数
    • 通过value,从指定的区间查找列表中的元素是否匹配
    • 匹配到第一个就立即返回索引,匹配不到跑出异常
  • 时间复杂度:
    • index和count方法的时间复杂度都是O(n)
    • 随着元素数据规模的增大,而效率下降
  • 可使用*+来形成新的列表,新元组可用变量接收,即存在返回值
  • len(元组):返回元组的长度
tuple_int = (1.43, [4, 6, 7], {"dict_key": "dict_value"},
             ("dkqakdf", 1.5), "fskfgv", 7)
print("查找元组中元素的位置:",tuple_int.index(1.43))  # 1.43的索引值
print("查找元组中元素的个数",tuple_int.count(7))  # 元组中7的个数
tuple_data = tuple_int*2
print("重复显示新的元组:",tuple_data)
tuple_item = tuple_data+tuple_int
print("相加得到新的元组:",tuple_item)
================结果===================
查找元组中元素的位置: 0
查找元组中元素的个数 1
重复显示新的元组: (1.43, [4, 6, 7], {'dict_key': 'dict_value'}, 
('dkqakdf', 1.5), 'fskfgv', 7, 1.43, [4, 6, 7], 
{'dict_key': 'dict_value'}, ('dkqakdf', 1.5), 'fskfgv', 7)
相加得到新的元组: (1.43, [4, 6, 7], {'dict_key': 'dict_value'}, 
('dkqakdf', 1.5), 'fskfgv', 7, 1.43, [4, 6, 7],
 {'dict_key': 'dict_value'}, ('dkqakdf', 1.5), 
 'fskfgv', 7, 1.43, [4, 6, 7], 
 {'dict_key': 'dict_value'}, ('dkqakdf', 1.5), 'fskfgv', 7)

元素类的定义——namedtuple

  • 先导入模块,然后定义元素的名称和变量,再对变量进行赋值
  • 导入模块
from collections import namedtuple
  • 定义类名和变量 类=namedtuple(“类名”,“变量1 变量2”),中间使用空格隔开
  • 变量=类名(“变量”,值)
  • 例子
from collections import namedtuple
Student = namedtuple("Student","name page")
tom = Student("tom",20)
haha = Student("haha",18)

#调用
print(tom.name)


====== 执行结果=====
tom

元祖和列表的使用场景和ipython

  • 使用ipython工具可以看到,创建元祖10万次和创建字典10万次所需时间不同,明显的创建元祖的时间更短
In [1]: timeit list_1 = [1,2,3]
34.9 ns ± 0.143 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)

In [2]: timeit tuple_1 = (1,2,3)
9.24 ns ± 0.0295 ns per loop (mean ± std. dev. of 7 runs, 100,000,000 loops each)
  • 这是因为元祖不可变,组内的元素固定,不可增删改查;列表可变,组内的元素不固定,灵活,可以实现增删改
  • 如果说存储的数据会发生变化——增删改,就是用列表;如果存储的数据不会发生变化,就是用元祖
  • ipython的使用方式:
  • 安装第三方库:pip install ipython 或者在setting中安装
  • 进入ipython:直接输入ipython命令即可
  • 退出ipython:exit
  • ipython特性:timeit 可以用来计算时间,安装ipython后,可以直接在py文件中导入
  • 如果计算一个函数的运行时间,直接在Timer的括号中输入函数名即可,不需要添加引号
import timeit

a = timeit.Timer("list_1 = [1,2,3]")
print(a.timeit(100))

命名元组

  • 元组的取值,一般是按照索引获取,命名元祖可以让元素的取值更加人性化,像字典一样取值
  • 命名元组的创建,需要导入内置模块:from collections import namedtuple
  • 命名元组中,field_names中的个数必须和后续设置的元素个数一直,否则会报错
from collections import namedtuple
stu_mes = namedtuple(typename="stu_mes", field_names=["name","age","language"])
# typename:类型名字;field_names:命名元祖取值的key
# 设置元祖的值
tu = stu_mes("fyc",18,"English")
print(tu)
print(tu.name,tu.age,tu.language)
# 命名元组中,field_names中的个数必须和后续设置的元素个数一直,否则会报错
tu = stu_mes("fyc",18,"English","aaa") # 报错

三、字典

字典的特点、格式,关键字

1.字典 dict{} 关键字:dict (关键字,不可用于命名 ) 符号:花括号 {}

  • 特点:可变无序(每次执行key和value的位置都会变化)的,其是根据键来取值的,也就是说字典不支持索引
  • 字典存在空字典 dict_1={}
  • 字典中的值是以键值对的形式出现,key:value,不同的键值对之间使用逗号(英文)进行隔开,但字典键值对之间的符号时冒号
  • 字典中的value可以是任意类型,key可以是字符串,整数,浮点数和元组。key必须是可hash的,即key必须是不可变类型,不能是可变类型(例如列表和字典)
  • 一般key都是字符串,90%
  • 字典中key的值必须是唯一的,不重复的,要不然前面的value会被后面的value覆盖掉
  • 因为字典是可变的,所以字典支持增删改查
  • 可以直接使用dict函数来定义,例如:d = dict(a=5,b=6,name=[1,2,3]);此种方式数字作为key可能不行,例如“1=2”会报错

代码及运行结果如下

d = dict(a=5,b=6,name=[1,2,3])
print(d)
dict_msg={}#空字典
print(type(dict_msg))
dict_msg={'class':'NET1101',7:8,(55,88):{"name":"yezi"}}
print(dict_msg)

==========run_result==========
{'a': 5, 'b': 6, 'name': [1, 2, 3]}
<class 'dict'>
{'class': 'NET1101', 7: 8, (55, 88): {'name': 'yezi'}}

字典的访问、取值、嵌套取值,获取函数

  • -查询:根据key进行查询 格式:字典名[key];使用此中方式,如果key不存在,就会抛出异常
  • 嵌套取值,与列表,字符串,元素的格式一致,不过他们取值的是下标,字典取值的是key
  • 取出所有的key值 格式:字典名.keys()
  • 取出所有的values值,格式:字典名.values()
  • 取出所有的键值对:格式:字典名.items()
  • 以上三个函数打印后,是将数据放在一个数据的集合中,其数据不是字典,也不是列表

代码及运行结果如下:

dict_msg = {'class': 'NET1101', 7: 8, 
(55, 88): {"name": "yezi"},"grade": [80, 90, 100, 200]}
print(dict_msg)
print(dict_msg["class"])  # 字典的取值,根据key取值
print(dict_msg[(55, 88)]["name"])  # 字典的嵌套取值,根据key来全套
print(dict_msg["grade"][2])#获取字典中嵌套列表的值,使用字典的key取值value,然后使用列表的索引取值
print(dict_msg.keys())# 获取所有的key值,返回数据类型为元组
print(dict_msg.values())# 获取所有的value值,返回数据类型为元组
print(dict_msg.items())  # 获取所有的键值对。返回数据类型为元组

在这里插入图片描述

  • 注意:字典中key的值是不能重复的,否则相同key的value值中,后面的会将前面的value覆盖掉、

示例代码如下:

dict_msg = {'class': 'NET1101', 'class': 8, 
(55, 88): {"name": "yezi"},"grade": [80, 90, 100, 200]}
print(dict_msg)

在这里插入图片描述

字典的get、setdefault函数

get函数

  • 存在return返回值,返回key对应的value值,key不存在则返回None
  • 如果在get中添加默认返回元素,代表若key不存在,则返回默认值
  • 代码示例:
d = dict(a=5,b=6,name=[1,2,3])
z = d.get("z",0)
a = d.get("a")
m = d.get("m")
print("get_result:{0},return_None:{1},return_set:{2}".format(
    a,m,z))

==========run_result===========
get_result:5,return_None:None,return_set:0

setdefault函数

  • 存在return返回值,返回key对应的value值,key不存在就在字典中添加新key,其对应的值为None,并将None返回
  • 如果设置初始值,则代表key不存在时,这个key的初始值为设定的值
  • 代码示例:
d = dict(a=5,b=6,name=[1,2,3])
z = d.setdefault("z")
z = d.setdefault("k",{})
print("run_dict:{0},return_z_value{1}".format(d,z))
a = d.setdefault("a")
print("return_a:{}".format(a))

======run_result==========
run_dict:{'a': 5, 'b': 6, 'name': [1, 2, 3], 'z': None, 'k': {}},return_z_value{}
return_a:5

字典的新增、删除与修改

新增和修改

格式:字典名[key]=value 如果key存在则为修改,如果key不存在则为新增

dict_msg={'class':'NET1101',7:8,(55,88):{"name":"yezi"}}
print(dict_msg)
dict_msg['class']='java1102'#修改clsss的值
print(dict_msg)
dict_msg['code']=100#新增字典的值
print(dict_msg)

在这里插入图片描述

update函数

  • 使用另外一个字典的健值对来更新本字典,没有返回值
  • key不存在,将健值对添加到字典中,key存在,就覆盖原本key的值
d = dict(a=5,b=6,name=[1,2,3])
print("原始:",d)
#age不存在,增加,name存在,修改
c = {"age":18,"name":"yezi"}
d.update(c)
print("修改后:",d)

=========run_result==========
原始: {'a': 5, 'b': 6, 'name': [1, 2, 3]}
修改后: {'a': 5, 'b': 6, 'name': 'yezi', 'age': 18}

删除

pop函数
  • 指定删除,语法:字典名.pop(key,default)
  • 与列表不同的是,因为字典时无序的,key不能不输入,否则会报错
  • 含义:key存在就移除,并返回已出的value
  • key不存在,返回给指定的default
  • default未设置,key不存在则会抛出异常
popitem
  • 随机删除语法:字典名.popitem()
  • 移除并返回任意一个健值对,字典如果为空,则抛出异常
clear和del
  • del 删除语句,del 字典名[key] 删除指定的键值对
  • 清空 d.clear()

代码及运行结果如下;

dict_msg={'class':'NET1101',7:8,(55,88):{"name":"yezi"},"code":100}
print("原始:",dict_msg)
a = dict_msg.pop('class')#删除指定的值,返回删除的value
print("删除之后",dict_msg)
print("删除的元素",a)

n = dict_msg.pop('class',"No")#删除不存在的值,返回默认返回值
print("删除不存在的key之后",dict_msg)
print("删除的元素",n)

del dict_msg[7] #del方法,删除指定的值
print("del删除指定元素7:",dict_msg)

b = dict_msg.popitem()#随机删除
print("删除之后",dict_msg)
print("删除的元素",b)

dict_msg.clear()#清空
print(dict_msg)

dict_msg.popitem()#字典为空,随机删除,抛出异常
================run_result===========
Traceback (most recent call last):
  File "Study_py/20220910.py", line 55, in <module>
    dict_msg.popitem()
KeyError: 'popitem(): dictionary is empty'

原始: {'class': 'NET1101', 7: 8, (55, 88): {'name': 'yezi'}, 'code': 100}
删除之后 {7: 8, (55, 88): {'name': 'yezi'}, 'code': 100}
删除的元素 NET1101
删除不存在的key之后 {7: 8, (55, 88): {'name': 'yezi'}, 'code': 100}
删除的元素 No
del删除指定元素7{(55, 88): {'name': 'yezi'}, 'code': 100}
删除之后 {(55, 88): {'name': 'yezi'}}
删除的元素 ('code', 100)
{}

del删除语句

  • del删除语句,后面跟什么,就代表删除什么,删除的是对象的引用(或者对象的名称)而不是对象本身
  • 注意引用类型(列表,字典,set),他们在进行修改的时候,本质上地址是不变的,一旦修改某个地址上的数值,其他对象在引用这个地址上的数值时,也会发生变化
a = True
b = [6]
print(id(b))
d = {"a":1,"b":b,"c":[1,3,5]}
del a  #删除了a这个变量
del d["c"]
print("删除d中,key为c的健值对",d)
del b[0]#因为内存id一样,所以列表不会生成新的对象
print("删除b这个对象中,指针为0的元素",b)
print("d中的b,他的值引用的对象为b",d,id(d["b"]))
c = b#将b赋值给了c,新建对象的引用,b和c公用一个对象地址
print("b和c公用一个id",c,id(c),id(b))
del c #删除了c,不会影响b
del b #删除了b,不会影响d,因为d中,key为b的值,也是对象的引用
==============run_result================

4348722112
删除d中,key为c的健值对 {'a': 1, 'b': [6]}
删除b这个对象中,指针为0的元素 []
d中的b,他的值引用的对象为b {'a': 1, 'b': []} 4348722112
b和c公用一个id [] 4348722112 4348722112
  • 以上代码执行中,因为b是列表(引用类型),修改时,是在原内存上进行修改,不会生成新的地址id,因此如果修改某一个引用类型的值,其他引用这个对象的数值也会发生变化
  • 判断引用对象是否新建的方式是:查看变量或者其他引用对象的地址是否相同

字典的遍历

字典的遍历,需要结合for循环来使用,具体的使用方式,详见:《python学习——for循环和while循环》中的for循环遍历字典。

字典的key

  • 字典的key要求和set的元素一样,都必须是可hash的(不可变类型)
  • set you去重的能力,其实字典也有去重的能力,字典是那key去重

变形的字典——缺省字典

defaultdict

  • 需要导入collections方法 from collections import defaultdict
  • 语法:defaultdict([default_factory[,……]]),注意,这个方法中传参为函数
  • 第一个参数是default_factory,缺省是None,他提供一个初始化函数作用是:当key不存在的时候,会调用这个工厂函数来生成key对应的value
from collections import defaultdict#导入
d1 = {}
#函数中,list()表示调用list函数,形成一个空列表,
# list是函数名称,表示列表函数本身,其是一个可调用的对象
#将list放到这里,表示list是defaultdict的初始化函数
#表示如果key没有value,调用这个函数,生成默认的value,凑成一个健值对
d2 = defaultdict(list)
print(d2,type(d2))#这是一个class类
#传统的方法,需要做判断
for k in "abcd":
    for v in range(5):
        if k not in d1.keys():
            d1[k] = []
        d1[k].append(v)
print(d1)

#使用defaultdict的方法,key缺少value,调用list函数生成,不需要加if判断
for k in "mnopq":
    for v in range(3):
        d2[k].append(v)
print(d2)
print("=======can use for ========")
for v,k in d2.items():
    print(v,k)

==========run_result===========
defaultdict(<class 'list'>, {}) <class 'collections.defaultdict'>
{'a': [0, 1, 2, 3, 4], 'b': [0, 1, 2, 3, 4], 'c': [0, 1, 2, 3, 4], 'd': [0, 1, 2, 3, 4]}
defaultdict(<class 'list'>, {'m': [0, 1, 2], 'n': [0, 1, 2], 'o': [0, 1, 2], 'p': [0, 1, 2], 'q': [0, 1, 2]})
=======can use for ========
m [0, 1, 2]
n [0, 1, 2]
o [0, 1, 2]
p [0, 1, 2]
q [0, 1, 2]

OrderedDict(3.5之前的版本)

  • 使用这个方法,需要导入 from collections import OrderedDict
  • 作用:给字典排序,打印的顺序并不是由放进去的value决定,而是由key加入的顺序决定,使用此方法之后,打印的key的顺序和放置key的顺序相同,从而打造排序的效果
from  collections import OrderedDict#导入
import random#导入随机数
d = {"b":3,"A":4,"z":6,"O":9,"o":10}
print("原本的字典:",d)
keys = list(d.keys())#将字典的key放置在一个字典中
#【备注】shuffle的作用是:将一个数组里面的元素随机打乱得到一个新的数组
random.shuffle(keys)#使用随机数打乱
print("随机打乱的字典的key",keys)
od = OrderedDict()#调用这个方法,生成一个对象,用来记录字典的顺序
for key in keys:
    od[key] = d[key]#将字典中的值,赋值给OrderedDict对象
print(od)
print(od.keys())#打印的顺序与加入的顺序一致

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值