再次优化通信录 ==================== 小白不断地在他的 list 中添加新的联系人,可是很快,他就发现随着联系人的增加,他的 list 越来越大。“哇靠,这么大的 list ,俺眼都花了!”。小白添加到了第 49 个同学的信息时,再也无法忍受这庞大的 list。“卧槽!这么大的通信录,而且联系人还是一个连着一个的,维护起来超麻烦。不行!看来我得寻找一个新的、可读性更高的数据储存方式了!”小白吼道。 “一个新的数据储存方式?该在哪才能找到这个新的数据储存方式呢?”小白思索道,他想起了他以前的知识几乎都是从《简明》 学来的。那么简明教程会不会有他这次想找的东西呢?小白翻开简明,他发现以前有关数据处理的 list 办法是出自于简明中 数据结构 一章。他想:“list 办法是出自这章的,那么,这章会不会有一些别的储存方式比这个 list 更简便的呢?”小白决定仔细看看简明中 数据结构 这章。 一点开这章,他就看到了这些东西: :: “数据结构基本上就是——它们是可以处理一些 数据 的 结构 。或者说,它们是用来存储一组相关数据的。 在Python中有三种内建的数据结构——列表、元组和字典。我们将会学习如何使用它们,以及它们如何使编程变得简单” “对,数据结构就是用来储存某些数据的,我只时用了数据结构中的列表,还有三个数据结构我没有学呢!”小白思索道。他感觉,这一节中就有他想要的东西。他仔细地,一页一页的继续看下去。突然他眼前一亮,发现了这些内容: .. image:: ../_static/snap/ch01-5-dict.png “字典?联系人?这也太巧了吧!怎么它的实例和我想做的是同一件东西”小白继续看下去,当他看到了简明中字典的实例和输出“Oh,这是神马东西嘛,输出这么乱,完全看不懂,还是自己试试看把它上面的实例打到 IDLE 里看会怎样吧!” 小白在 Idle 中输入了实例中的语句,并进行了自己的理解。 :: #(实例引用自简明) >>> ab = { 'Swaroop' : 'swaroopch@byteofpython.info', 'Larry' : 'larry@wall.org', 'Matsumoto' : 'matz@ruby-lang.org', 'Spammer' : 'spammer@hotmail.com' } #这里应该就是新定义一个字典吧? >>> print ab {'Swaroop': 'swaroopch@byteofpython.info', 'Matsumoto': 'matz@ruby-lang.org', 'Larry': 'larry@wall.org', 'Spammer': 'spammer@hotmail.com'} #果然新定义了一个字典 >>> print "Swaroop's address is %s" % ab['Swaroop'] #咦?print 后面跟了一个 ab['Swaroop'] 难道这是读取 ab 中的 Swaroop? Swaroop's address is swaroopch@byteofpython.info #好像是输出 Swaroop 后面的信息 swaroopch@byteofpython.info 了。 >>> print ab['Swaroop'] #试试单独打印 ab['Swaroop'] 试试 swaroopch@byteofpython.info #哇塞,果然输出了 ab['Swaroop'] 后面的值,看来只要用 字典名['字典中要读取的键'] 这种格式就能读取到字典中的值了 >>> ab['Guido'] = 'guido@python.org' #这句有事干什么用呢?字典 ab 中并没有 Guido 这个键啊? >>> print ab['Guido'] #打印 Guido ?可字典里面没有这个键啊? guido@python.org #字典中好像又多了 Guido 这个键了,莫非上一句是在字典中添加 Guido 这个键吗?赶快看看! >>> print ab {'Swaroop': 'swaroopch@byteofpython.info', 'Matsumoto': 'matz@ruby-lang.org', 'Larry': 'larry@wall.org', 'Spammer' : 'spammer@hotmail.com','Guido': 'guido@python.org'} #果然多出了 Guido 这个键,看来那一句果然是用于添加字典中的键值的 >>> del ab['Spammer'] #del?删?难道这是删除字典中的某个键吗? >>> print ab['Spammer'] #打印出来看看? Traceback (most recent call last): #出错,看来果然是删掉那个键值了 File "", line 1, in print ab['Spammer'] KeyError: 'Spammer' >>> “哈哈,这个字典真是太好用了,竟然能通过对应的键列出对应的值,太棒了,这样我的通信录又能简化不少啊,连 list 都不用用了,而且看着还清楚,真是太方便了”小白迫不及待想要把他的通信录改成用字典的通信录。“对,咱就先用字典实现读取联系人功能,再实现添加联系人功能,一步步来。”小白马上动起手来。 :: _Info = {"张三":54321, "李四":12345} _run = True while _run: _User_input = raw_input("输入联系人名:") print _Info[_User_input] 小白尝试着运行它的程序: :: >>> 输入联系人名:张三 54321 输入联系人名:李四 12345 输入联系人名:王五 Traceback (most recent call last): File "E:/test.py", line 7, in print _Info[_User_input] KeyError: '\xcd\xf5\xce\xe5' >>> “对哇,没有作一个判断,以判断用户输入的键是否在字典里,这样的话如果用户输入一个不存在的键的话,程序就会像这样报错了,可是,怎样才能判断字典里面有没有某个键呢?直接读取不存在的键是肯定不行的呀,这样肯定出错!有没有判断一个字典里面有没有某个键的办法呢?”这时,小白想到了一个绝对能找到答案的办法:python 的 help() “对嘛,前面早就已经知道python有help()这个办法了,为何不用一下呢?”小白在简明中已经知道了字典的E文是 dict 。“那么,只要 help(dict) 不就可以查看到所有有关字典的用法了吗?”小白马上动手。 :: >>> help(dict) Help on class dict in module __builtin__: class dict(object) | dict() -> new empty dictionary | dict(mapping) -> new dictionary initialized from a mapping object's | (key, value) pairs | dict(iterable) -> new dictionary initialized as if via: | d = {} | for k, v in iterable: | d[k] = v | dict(**kwargs) -> new dictionary initialized with the name=value pairs | in the keyword argument list. For example: dict(one=1, two=2) | | Methods defined here: | | __cmp__(...) | x.__cmp__(y) <==> cmp(x,y) | | __contains__(...) | D.__contains__(k) -> True if D has a key k, else False | | __delitem__(...) | x.__delitem__(y) <==> del x[y] | | __eq__(...) | x.__eq__(y) <==> x==y | | __ge__(...) | x.__ge__(y) <==> x>=y | | __getattribute__(...) | x.__getattribute__('name') <==> x.name | | __getitem__(...) | x.__getitem__(y) <==> x[y] | | __gt__(...) | x.__gt__(y) <==> x>y | | __init__(...) | x.__init__(...) initializes x; see help(type(x)) for signature | | __iter__(...) | x.__iter__() <==> iter(x) | | __le__(...) | x.__le__(y) <==> x<=y | | __len__(...) | x.__len__() <==> len(x) | | __lt__(...) | x.__lt__(y) <==> x x!=y | | __repr__(...) | x.__repr__() <==> repr(x) | | __setitem__(...) | x.__setitem__(i, y) <==> x[i]=y | | __sizeof__(...) | D.__sizeof__() -> size of D in memory, in bytes | | clear(...) | D.clear() -> None. Remove all items from D. | | copy(...) | D.copy() -> a shallow copy of D | | get(...) | D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None. | | has_key(...) | D.has_key(k) -> True if D has a key k, else False | | items(...) | D.items() -> list of D's (key, value) pairs, as 2-tuples | | iteritems(...) | D.iteritems() -> an iterator over the (key, value) items of D | | iterkeys(...) | D.iterkeys() -> an iterator over the keys of D ...... 小白仔细观察 help 出来的东东,这时,一个叫 has_key 的东东吸引了他的注意: :: | has_key(...) | D.has_key(k) -> True if D has a key k, else False “True if D has a key k, else False?如果字典 D 有键 k 就返回 True,否则返回 False?这正是我需要的!看样子,它的用法就是 D.has_key(k) 嘛,马上试一下看到底是不是这样用的!”小白马上打开 IDLE 进行了尝试: :: >>> _Info = {"张三":54321, "李四":12345} >>> >>> _Info.has_key("张三") True >>> _Info.has_key("hello") False >>> “哈哈,真的是这样。接下来只要在在原程序上加个 if ,用 has_key 判断就可以了。”小白迅速动作: :: _Info = {"张三":54321, "李四":12345} _run = True while _run: _User_input = raw_input("输入联系人名:") if _Info.has_key(_User_input) == True: print _Info[_User_input] elif _User_input == "退出": _run = False else: print "无此联系人" “运行试试。”小白对他的程序进行调试。 :: >>> 输入联系人名:张三 54321 输入联系人名:李四 12345 输入联系人名:王五 无此联系人 输入联系人名:退出 >>> 小白敲打着键盘:“Ok,成功,一切都在意料之中,这字典真是太方便了,接下来就是把我已经知道的 ab['Guido'] = 'guido@python.org' 这个用法添加到程序中就能实现联系人添加功能了。”: :: _Info = {"张三":54321, "李四":12345} _run = True while _run: _User_input = raw_input("输入联系人名:") if _Info.has_key(_User_input) == True: print _Info[_User_input] elif _User_input == "增加": _New_Name = raw_input("输入要增加的联系人名:") _New_Info = raw_input("输入该联系人的信息:") _Info[_New_Name] = _New_Info elif _User_input == "退出": _run = False else: print "无此联系人" “搞定!调试一下程序看会不会有问题。”小白想。 :: 输入联系人名:张三 54321 输入联系人名:李四 12345 输入联系人名:王五 无此联系人 输入联系人名:增加 输入要增加的联系人名:王二麻子 输入该联系人的信息:123333 输入联系人名:王二麻子 123333 输入联系人名:退出 >>> “好,程序果然没有问题。诶?”小白敲了敲自己的脑袋。“如果这样做的话就会有一个 bug ,用户退出了程序之后他添加的联系人就全都没了!前面的 list 通信录添加功能也有这个问题,怎样才能解决他们呢?”小白又陷入新的思考中...... (第一章完)