zoukankan      html  css  js  c++  java
  • 第25~26讲:字典:当索引不好用时

    一 字典https://www.cnblogs.com/linupython/p/5880280.html

    1 概念/特点

    • 字典是另一种可变容器模型,且可存储任意类型对象。
    • 字典是python中唯一的映射类型,采用键值对(key-value)的形式存储数据。python对key进行哈希函数运算,根据计算的结果决定value的存储地址,所以字典是无序存储的,且key必须是可哈希的,可哈希表示键值不可变。

    总结:

    • 字典值可以没有限制地取任何python对象,既可以是标准的对象,也可以是用户定义的,但键不行。
    • 不允许同一个键出现两次。创建时如果同一个键被赋值两次,后一个值会被记住
    • 键必须不可变,所以可以用数字,字符串或元组充当,所以用列表就不行

    2 定义:字典可通过一对花括号来定义,元素内部通过冒号来连接key和对应的value,元素与元素之间通过逗号隔开,可进行自由嵌套。

    3 语法格式:d = {key1 : value1, key2 : value2 }

    4 字典的相关操作

    • 创建
      • 通过定义字典的过程创建 。 dict = {'a':1,'b':2,'c':3}
      • dict()函数:也可以创建字典,工厂函数/类型函数
        • 注意:在使用dict函数之前先把原来定义的dict字典给删了,用'del dict'命令,否则系统会报错:TypeError: 'dict' object is not callable
        • 通过元组定义:dict1 = dict((('F',70),('i',105),('s',115),('h',104),('C',67)))
        • 通过关键字定义:dict1 = dict(a = 97,b=98)
    • 访问:通过在方括号内引用其键名来访问字典的元素。 print(dict['c'])
    • 修改:
      • 更改已有键值对的值:通过引用其键名来更改特定项的值。dict['a'] = 0
      • 增加新的键值对:通过引用要添加的'key'并给该'key'赋值来添加新的键值对: dict['d']=4
    • 删除:字典长度:获取字典的长度(键值对的个数),通过len方法实现。 len(dict)
      • del语句:
        • 删除整个字典。del dict
        • 删除字典中的某个键值对。del dict['a']
      • clear()方法:清空字典所有键值对,不需要参数。dict.clear()
      • pop()方法:删除字典的某一键值对,其参数直接是键值key,不需要通过字典名称引用。dict.pop('c')
      • popitem() 方法:删除最后插入的项目(在 3.7 之前的版本中,删除随机项目)。 dict.popitem()
    • 字典长度:获取字典的长度(键值对的个数),通过len方法实现。len(dict)
    • 字典排序:通过sorted方法对所有的key进行排序并以列表形式返回。 sorted(dict)
    • 字典类型: 可用type函数查看字典中某一键值对的值的类型。type(dict['a'])
    • 检查键值是否存在:要确定字典中是否存在指定的键,可使用 in 关键字。
      • 1 >>> if 'a' in dict:
        2 ...     print("True")
    • 遍历字典:可以使用 for 循环遍历字典,循环遍历字典时,返回值是字典的键,但也有返回值的方法。
      • 逐个打印字典中的所有键名:
        • 1 >>> for x in dict:
          2 ...     print(x)
      • 逐个打印字典中的所有值:
        • 1 >>> for x in dict:
          2 ...     print(dict[x])
      • 还可以使用 values() 函数返回字典的值
        • 1 >>> for x in dict.values():
          2 ...     print(x)
      • 通过使用 items() 函数遍历键和值
        • >>> for x,y in dict.items():
           ...     print(x,y)

    5  字典的常用内置方法

    (1)fromkeys()方法

    • 描述:Python 字典 fromkeys() 函数用于创建一个新字典,以序列 seq 中元素做字典的键,value 为字典所有键对应的初始值。
    • 语法:dict.fromkeys(seq[, value])
    • 参数:
      • seq -- 字典键值列表。
      • value -- 可选参数, 设置键序列(seq)的值,该参数只能有一个,并且所有键值列表对应的值都是它。
    • 返回值:该方法返回一个新字典。
    • 举例:
    •  1 >>> dict1 = {}
       2 >>> dict1.fromkeys((1,2,3))
       3 {1: None, 2: None, 3: None}
       4 
       5 >>> dict1.fromkeys((1,2,3),'Number')
       6 {1: 'Number', 2: 'Number', 3: 'Number'}
       7 
       8 >>> dict1.fromkeys((1,2,3),('one','two','three'))
       9 {1: ('one', 'two', 'three'), 2: ('one', 'two', 'three'), 3: ('one', 'two', 'three')}
      10 
      11 >>> dict1.fromkeys((1,3),'数字')  # 无法修改字典的值,会返回一个新的字典
      12 {1: '数字', 3: '数字'}

    (2)keys()方法

    • 描述:Python 字典(Dictionary) keys() 函数以列表返回一个字典所有的键。
    • 语法:dict.keys()
    • 参数:无参数
    • 返回值:返回一个字典所有的键。
    • 举例:
    • 1 >>> dict1 = {'a':1,'b':2,'c':3}
      2 >>> dict1.keys()
      3 dict_keys(['a', 'b', 'c'])

    (3)values()方法

    • 描述:Python 字典(Dictionary) values() 函数以列表返回字典中的所有值。
    • 语法:dict.values()
    • 参数:无参数
    • 返回值:返回字典中的所有值。
    • 举例:
    • 1 >>> dict1.values()
      2 dict_values([1, 2, 3])

    (4)items()方法

    • 描述:Python 字典(Dictionary) items() 函数以列表返回可遍历的(键, 值) 元组数组。
    • 语法:dict.items()
    • 参数:无参数
    • 返回值:返回可遍历的(键, 值) 元组数组。
    • 举例:
    • 1 >>> dict1.items()
      2 dict_items([('a', 1), ('b', 2), ('c', 3)])

    (5)get()方法

    • 描述:Python 字典(Dictionary) get() 函数返回指定键的值,如果值不在字典中返回默认值。
    • 语法:dict.get(key, default=None)
    • 参数:
      • key -- 字典中要查找的键。
      • default -- 如果指定键的值不存在时,返回该默认值。
    • 返回值:返回指定键的值,如果值不在字典中返回默认值None。
    • 举例:>>> dict1.get('a')

    (6)clear()方法:

    • 描述:Python 字典(Dictionary) clear() 函数用于删除字典内所有元素。
    • 语法:dict.clear()
    • 参数:无参数
    • 返回值:该函数没有任何返回值。
    • 举例:
    • 1 >>> dict1.clear()
      2 >>> dict1
      3 {}

    (7)copy()方法

    • 描述:Python 字典(Dictionary) copy() 函数返回一个字典的浅复制。
    • 语法:dict.copy()
    • 参数:无参数
    • 返回值:返回一个字典的浅复制。
    • 举例:
    • 1 >>> dict1.clear()
      2 >>> dict1
      3 {}
      4 >>> dict2
      5 {}
      6 >>> dict3
      7 {'a': 1, 'b': 2, 'c': 3}

    (8)pop()方法

    • 描述:Python 字典 pop() 方法删除字典给定键 key 及对应的值,返回值为被删除的值。key 值必须给出。 否则,返回 default 值。
    • 语法:dict.pop(key[,default])
    • 参数:
      • key: 要删除的键值
      • default: 如果没有 key,返回 default 值
    • 返回值:返回被删除的值。
    • 举例:
    • 1 >>> dict3
      2 {'a': 1, 'b': 2, 'c': 3}
      3 >>> dict3.pop('c')
      4 3
      5 >>> dict3
      6 {'a': 1, 'b': 2}

    (9)popitem()方法

    • 描述:Python 字典 popitem() 方法返回并删除字典中的最后一对键和值。如果字典已经为空,却调用了此方法,就报出 KeyError 异常。
    • 语法:dict.popitem()
    • 参数:无参数
    • 返回值:返回一个键值对(key,value)形式。
    • 1 >>> dict3
      2 {'a': 1, 'b': 2}
      3 >>> dict3.popitem()
      4 ('b', 2)
      5 >>> dict3
      6 {'a': 1}

    (10)setdefault()方法

    • 描述:Python 字典 setdefault() 函数和 get()方法 类似, 如果键不存在于字典中,将会添加键并将值设为默认值/设置的值。
    • 语法:dict.setdefault(key, default=None)
    • 参数:
      • key -- 查找的键值。
      • default -- 键不存在时,设置的默认键值。
    • 返回值:如果字典中包含有给定键,则返回该键对应的值,否则返回为该键设置的值
    • 举例:
    • 1 >>> dict3 = {'a':1}
      2 >>> print(dict3.setdefault('b'))
      3 None
      4 >>> dict3
      5 {'a': 1, 'b': None}
      6 >>> print(dict3.setdefault('a',3))
      7 1
      8 >>> print(dict3.setdefault('c',3))
      9 3

    (11)update()方法

    • 描述:Python 字典(Dictionary) update() 函数把字典dict2的键/值对更新到dict1里。
    • 语法:dict1.update(dict2)
    • 参数:dict2 -- 添加到指定字典dict1里的字典。
    • 返回值:该方法没有任何返回值。
    • 举例:
    • 1 >>> dict3
      2 {'a': 1, 'b': None, 'c': 3}
      3 >>> dict1 = {'d':4,'e':5}
      4 >>> dict3.update(dict1)
      5 >>> dict3
      6 {'a': 1, 'b': None, 'c': 3, 'd': 4, 'e': 5}
      7 >>> dict1
      8 {'d': 4, 'e': 5}

    6 字典和列表的对比

    字典的特殊性在于,内部存放的顺序与key存入的顺序没有任何关系,因为它本身就是无序的。字典与列表对比特点如下:

    • 字典:
      • 查找和插入的速度极快,不会随着key的增加而变慢
      • 需要占用大量的内存(浪费比较多)
    • 列表:
      • 查找和插入的时间随着元素的增加而增加
      • 占用空间小,内存浪费少

    综上所述,字典是在用空间换取时间(执行效率)。

    二 课后习题

    (一)测试题部分

    第25讲:

    0. 当你听到小伙伴们在谈论“映射”、“哈希”、“散列”或者“关系数组”的时候,事实上他们就是在讨论什么呢?

    答:是的,事实上他们就是在讨论我们这一讲介绍的“字典”,都是一个概念!

    1. 尝试一下将数据('F': 70, 'C': 67, 'h': 104, 'i': 105, 's': 115)创建为一个字典并访问键 'C' 对应的值?

    1 >>> MyDict = dict((('F', 70), ('i',105), ('s',115), ('h',104), ('C',67)))
    2 >>> MyDict_2 = {'F':70, 'i':105, 's':115, 'h':104, 'C':67}
    3 >>> type(MyDict)
    4 <class 'dict'>
    5 >>> type(MyDict_2)
    6 <class 'dict'>
    7 >>> MyDict['C']
    8 67

     2. 用方括号(“[]”)括起来的数据我们叫列表,那么使用大括号(“{}”)括起来的数据我们就叫字典,对吗?

    1 >>> NotADict = {1, 2, 3, 4, 5}
    2 >>> type(NotADict)
    3 <class 'set'>

    不难发现,虽然我们用大括号(“{}”)把一些数据括起来了,但由于没有反映出这些数据有映射的关系,所以创建出来的不是字典,而是叫’set’的东西,那’set’到底又是啥玩意儿呢?请看第027讲 | 集合:在我的世界里,你就是唯一!

    3. 你如何理解有些东西字典做得到,但“万能的”列表却难以实现?

    1 >>> brand = ['李宁', '耐克', '阿迪达斯', '鱼C工作室']
    2 >>> slogan = ['一切皆有可能', 'Just do it', 'Impossible is nothing', '让编程改变世界']
    3 >>> print('鱼C工作室的口号是:', slogan[brand.index('鱼C工作室')])
    4 鱼C工作室的口号是: 让编程改变世界

    列表brand、slogan的索引和相对的值是没有任何关系的,我们可以看出唯一有联系的就是两个列表间,索引号相同的元素是有关系的(品牌对应口号嘛),所以这里我们通过brand.index('鱼C工作室')这样的语句,间接的实现通过品牌查找对应的口号的功能。
      
    这确实是一种可实现方法,呃……但用起来呢,多少有些别扭,效率还不高咧。况且Python是以简洁为主,这样子的实现肯定是不能让人满意的,所以呢,我们需要有字典这种映射类型的出现:

    1 >>> dict1 = {'李宁':'一切皆有可能', '耐克':'Just do it', '阿迪达斯':'Impossible is nothing', '鱼C工作室':'让编程改变世界'}
    2 >>> print('鱼C工作室的口号是:', dict1['鱼C工作室'])
    3 鱼C工作室的口号是: 让编程改变世界

    4. 下边这些代码,他们都在执行一样的操作吗?你看得出差别吗?

    1 >>> a = dict(one=1, two=2, three=3)
    2 >>> b = {'one': 1, 'two': 2, 'three': 3}
    3 >>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
    4 >>> d = dict([('two', 2), ('one', 1), ('three', 3)])
    5 >>> e = dict({'three': 3, 'one': 1, 'two': 2})

    答:是的,他们都在创建字典:a = dict(one=1, two=2, three=3),没有差别

    5. 如图,你可以推测出打了马赛克部分的代码吗?

    嗯,我很傻的用分片的方式一个一个写的,我好呆。。。(data[0:3],data[5:7],data[9:])

    1 data = "1000,小甲鱼,男"
    2 MyDict = {}
    3 # 还记得字符串的分割方法吧,别学过就忘啦^_^
    4 (MyDict['id'], MyDict['name'], MyDict['sex']) = data.split(',') 
    5 
    6 print("ID:   " + MyDict['id'])
    7 print("Name: " + MyDict['name'])
    8 print("Sex   " + MyDict['sex'])

    第26讲:

    0. Python的字典是否支持一键(Key)多值(Value)?

    答:不支持,对相同的键再次赋值会将上一次的值直接覆盖。

    1. 在字典中,如果试图为一个不存在的键(Key)赋值会怎样?

    答:会自动创建对应的键(Key)并添加相应的值(Value)进去。(具体原理可以参考第3题的“扩展阅读”部分)

    2. 成员资格操作符(in和not in)可以检查一个元素是否存在序列中,当然也可以用来检查一个键(Key)是否存在字典中,那么请问哪种的检查效率更高些?为什么?

    答:在字典中检查键(Key)是否存在比在序列中检查指定元素是否存在更高效。因为字典的原理是使用哈希算法存储,一步到位,不需要使用查找算法进行匹配,因此时间复杂度是O(1),效率非常高。(关于如何使用哈希算法存储的具体原理可以参考第3题的“扩展阅读”部分)

    3. Python对键(Key)和值(Value)有没有类型限制?

    答:Python对键的要求相对要严格一些,要求它们必须是可哈希(Hash)的对象,不能是可变类型(包括变量、列表、字典本身等)。

    但是Python对值是没有任何限制的,它们可以是任意的Python对象。
    如果不清楚哈希原理以及字典的存放原理的童鞋,推荐阅读下小甲鱼帮你整理的这篇文章:你知道Python的字典(Dict)是如何存储的吗?(http://bbs.fishc.com/thread-45016-1-1.html

    4. 请目测下边代码执行后,字典dict1的内容是什么?

    1 >>> dict1.fromkeys((1, 2, 3), ('one', 'two', 'three')) 
    2 >>> dict1.fromkeys((1, 3), '数字')

    答:执行完成后,字典dict1的内容是:{1: '数字', 3: '数字'}
    这里要注意的是,fromkeys方法是直接创建一个新的字典,不要试图使用它来修改一个原有的字典,因为它会直接无情的用把整个字典给覆盖掉。

    5. 如果你需要将字典dict1 = {1: 'one', 2: 'two', 3: 'three'}拷贝到dict2,你应该怎么做?

    答:可以利用字典的copy()方法:dict2 = dict1.copy(),在其他语言转移到Python小伙伴们刚开始可能会习惯性的直接用赋值的方法(dict2 = dict1),这样子做在Python中只是将对象的引用拷贝过去而已。

    (二)动动手部分:

    第25讲:

    0. 尝试利用字典的特性编写一个通讯录程序吧!

     我的代码:(感觉我的代码比小甲鱼的代码要聪明一点,哈哈哈哈)

     1 # -*- coding:utf-8 -*-
     2 def printInfo():
     3     print("|--- 欢迎进入通讯录程序 ---|")
     4     print("|--- 1:查询联系人资料 ---|")
     5     print("|--- 2:插入新的联系人 ---|")
     6     print("|--- 3:删除已有联系人 ---|")
     7     print("|--- 4:退出通讯录程序 ---|")
     8     print()
     9 
    10 def find(addressDict):
    11     print(addressDict)
    12     name = input("请输入联系人姓名:")
    13     if name in addressDict:
    14         print(f"{name}:{addressDict[name]}")
    15         return addressDict
    16     else:
    17         print("用户不存在,请重新选择相应操作!")
    18         return addressDict
    19 
    20 def insert(addressDict):
    21     name = input("请输入联系人姓名:")
    22     if name in addressDict:
    23         print("您输入的姓名在通讯录中已存在",end = '')
    24         print(f"-->> {name}:{addressDict[name]}")
    25         i= input("是否修改用户资料(YES/NO):")
    26         if i == YES:
    27             addressDict[name]=input("请输入用户联系电话:")
    28             return addressDict
    29         else:
    30             return main()
    31             return addressDict
    32     else:
    33         addressDict[name]=input("请输入用户联系电话:")
    34         return addressDict
    35 
    36 def delete(addressDict):
    37     name = input("请输入联系人姓名:")
    38     if name in addressDict:
    39         del addressDict[name]
    40         return addressDict
    41     else:
    42         print("用户不存在,请重新选择相应操作!")
    43         return addressDict
    44 
    45 def over():
    46     print("|--- 感谢使用通讯录程序 ---|")
    47     exit()
    48 
    49 def main():
    50     addressDict = {}
    51     printInfo()
    52     while 1:
    53         print(f"addressDict = {addressDict}")
    54         num = int(input("请输入相关的指令代码:"))
    55 
    56         if num == 1:
    57             find(addressDict)
    58         elif num == 2:
    59             insert(addressDict)
    60         elif num == 3:
    61             delete(addressDict)
    62         elif num == 4:
    63             over()
    64         else:
    65             print("输入错误,请重新输入数字:1或2或3或4 选择相应的操作")
    66         print()
    67 
    68 main()

    小甲鱼的代码:

     1 print('|--- 欢迎进入通讯录程序 ---|')
     2 print('|--- 1:查询联系人资料  ---|')
     3 print('|--- 2:插入新的联系人  ---|')
     4 print('|--- 3:删除已有联系人  ---|')
     5 print('|--- 4:退出通讯录程序  ---|')
     6 
     7 contacts = dict()
     8 
     9 while 1:
    10     instr = int(input('
    请输入相关的指令代码:'))
    11     
    12     if instr == 1:
    13         name = input('请输入联系人姓名:')
    14         if name in contacts:
    15             print(name + ' : ' + contacts[name])
    16         else:
    17             print('您输入的姓名不再通讯录中!')
    18 
    19     if instr == 2:
    20         name = input('请输入联系人姓名:')
    21         if name in contacts:
    22             print('您输入的姓名在通讯录中已存在 -->> ', end='')
    23             print(name + ' : ' + contacts[name])
    24             if input('是否修改用户资料(YES/NO):') == 'YES':
    25                 contacts[name] = input('请输入用户联系电话:')
    26         else:
    27             contacts[name] = input('请输入用户联系电话:')
    28 
    29     if instr == 3:
    30         name = input('请输入联系人姓名:')
    31         if name in contacts:
    32             del(contacts[name])         # 也可以使用dict.pop()
    33         else:
    34             print('您输入的联系人不存在。')
    35             
    36     if instr == 4:
    37         break
    38 
    39 print('|--- 感谢使用通讯录程序 ---|')

    第·26讲:

    0. 尝试编写一个用户登录程序(这次尝试将功能封装成函数)

     小甲鱼代码:

     1 user_data = {}
     2 
     3 def new_user():
     4     prompt = '请输入用户名:'
     5     while True:
     6         name = input(prompt)
     7         if name in user_data:
     8             prompt = '此用户名已经被使用,请重新输入:'
     9             continue
    10         else:
    11             break
    12 
    13     passwd = input('请输入密码:')
    14     user_data[name] = passwd
    15     print('注册成功,赶紧试试登录吧^_^')
    16 
    17 def old_user():
    18     prompt = '请输入用户名:'
    19     while True:
    20         name = input(prompt)
    21         if name not in user_data:
    22             prompt = '您输入的用户名不存在,请重新输入:'
    23             continue
    24         else:
    25             break
    26     
    27     passwd = input('请输入密码:')
    28     pwd = user_data.get(name)
    29     if passwd == pwd:
    30         print('欢迎进入XXOO系统,请点右上角的X结束程序!')
    31     else:
    32         print('密码错误!')
    33 
    34 def showmenu():
    35     prompt = '''
    36 |--- 新建用户:N/n ---|
    37 |--- 登录账号:E/e ---|
    38 |--- 推出程序:Q/q ---|
    39 |--- 请输入指令代码:'''
    40 
    41     while True:
    42         chosen = False
    43         while not chosen:
    44             choice = input(prompt)
    45             if choice not in 'NnEeQq':
    46                 print('您输入的指令代码错误,请重新输入:')
    47             else:
    48                 chosen = True
    49 
    50         if choice == 'q' or choice == 'Q':
    51             break
    52         if choice == 'n' or choice == 'N':
    53             new_user()
    54         if choice == 'e' or choice == 'E':
    55             old_user()
    56 
    57 showmenu()
  • 相关阅读:
    UIButton 动态改变文本闪烁问题
    利用GDataXML解析XML文件
    限制键盘只能输入数字
    获得view所在的控制器
    使用Canvas绘制简单的时钟控件
    Spring整合ActiveMq消息队列
    Symmetric Key Encryption DES
    OSPF 高级实验
    OSPF 基础实验
    EIGRP 高级实验
  • 原文地址:https://www.cnblogs.com/luoxun/p/13356547.html
Copyright © 2011-2022 走看看