再次优化通信录¶
小白不断地在他的 list 中添加新的联系人,可是很快,他就发现随着联系人的增加,他的 list 越来越大。“哇靠,这么大的 list ,俺眼都花了!”。小白添加到了第 49 个同学的信息时,再也无法忍受这庞大的 list。“卧槽!这么大的通信录,而且联系人还是一个连着一个的,维护起来超麻烦。不行!看来我得寻找一个新的、可读性更高的数据储存方式了!”小白吼道。
“一个新的数据储存方式?该在哪才能找到这个新的数据储存方式呢?”小白思索道,他想起了他以前的知识几乎都是从《简明》 学来的。那么简明教程会不会有他这次想找的东西呢?小白翻开简明,他发现以前有关数据处理的 list 办法是出自于简明中 数据结构 一章。他想:“list 办法是出自这章的,那么,这章会不会有一些别的储存方式比这个 list 更简便的呢?”小白决定仔细看看简明中 数据结构 这章。
一点开这章,他就看到了这些东西:
“数据结构基本上就是——它们是可以处理一些 数据 的 结构 。或者说,它们是用来存储一组相关数据的。
在Python中有三种内建的数据结构——列表、元组和字典。我们将会学习如何使用它们,以及它们如何使编程变得简单”
“对,数据结构就是用来储存某些数据的,我只时用了数据结构中的列表,还有三个数据结构我没有学呢!”小白思索道。他感觉,这一节中就有他想要的东西。他仔细地,一页一页的继续看下去。突然他眼前一亮,发现了这些内容:
“字典?联系人?这也太巧了吧!怎么它的实例和我想做的是同一件东西”小白继续看下去,当他看到了简明中字典的实例和输出“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 "<pyshell#7>", line 1, in <module>
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 <module>
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<y
|
| __ne__(...)
| x.__ne__(y) <==> 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 通信录添加功能也有这个问题,怎样才能解决他们呢?”小白又陷入新的思考中......
(第一章完)