# coding:utf-8

#---------------------------------------------  创建和使用字典  ---------------------------------------------


#电话簿示例

names = ['Alice', 'Neth', 'Cecil', 'Dee-Dee', 'Earl']

numbers = ['2341', '9102', '3158', '0142', '5551']

print numbers[names.index('Cecil')]       ##查找Cecil电话,列表方式,希望字典方式:phonebook['Cecil']

#3158


#字典方式

phonebook = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3158'}   #名字是键,电话是值,键是唯一的,值不是唯一的。

print phonebook['Cecil']

#3158

#dict

#可以用dict函数通过其他映射或者对的序列建立字典

items = [('name', 'Gumby'), ('age', 42)]

d = dict(items)

print d

#{'age': 42, 'name': 'Gumby'}

d = dict(name='Gumby', age=42)      #也可以通过关键字参数来创建字典

print d

#{'age': 42, 'name': 'Gumby'}

#x = []

#x[42] = 'foobar'   #字符串foor关联到一个空列表42号位置上,显然是不可能的,因为这个位置根本不存在。为了将变成可能,我必须用[None]*43

x = {}

x[42] = 'foobar'   #字典可以,我将'foobar'关联到空字典的键42上

print x

#{42: 'foobar'}


#字典的格式化字符串

#如果使用的是字典(以字符串作为键)而不是元组,使用字符串格式化方式更酷一些,在每个转换说明符中的%字符后面,可以加上键(用圆括号括起来),后面再跟上其他说明元素。

phonebook = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3158'}

print "Cecil's phone number is %(Cecil)s." % phonebook        #百分号后面加上键(圆括号括起来)

#Cecil's phone number is 3158.

#当以这种方式使用字典的时候,只要所有给出的键都能在字典中找到,就可以使用任意数量的转换说明符。这类字符串格式化在模板系统中非常有用。

template = '''<html>

<head><title>%(title)s</title></head>

<body>

<h1>%(title)s</h1>

<p>%(text)s</p>

</body>'''

data = {'title': 'My Home Page', 'text': 'Welcome to my home page!'}

print template % data             #html例子,格式化模板很方便

#<html>

#<head><title>My Home Page</title></head>

#<body>

#<h1>My Home Page</h1>

#<p>Welcome to my home page!</p>

#</body>


#--------------------------------------------  字典方法  -------------------------------------------------------


#clear

#清除字典中所有的项。这是个原地操作(类似list.sort),所以无返回值(或者说返回None)

d = {}

d['name'] = 'Gumby'

d['age'] = 42

print d

#{'age': 42, 'name': 'Gumby'}

returned_value = d.clear()

print d

#{}

print returned_value

#None

x = {}

y = x

x['key'] = 'value'

print y

#{'key': 'value'}

x = {}          #x变量被清空

print y        #y变量字典仍然存在,如果想彻底清空,就需要用到clear

#{'key': 'value'}

x = {}

y = x

x['key'] = 'value'

print y

#{'key': 'value'}

x.clear()

print x

#{}

print y         #x和y一起被清空

#{}


#copy

#copy方法返回一个具有相同键-值对的新字典(这个方法实现的是浅复制,因为值本身就是相同的,而不是副本)。

x = {'username': 'admin', 'machines': ['foo', 'bar', 'baz']}

y = x.copy()

print y

#{'username': 'admin', 'machines': ['foo', 'bar', 'baz']}

y['username'] = 'mlh'    #替换不会修改原始字典x变量

print y

#{'username': 'mlh', 'machines': ['foo', 'bar', 'baz']}

print x

#{'username': 'admin', 'machines': ['foo', 'bar', 'baz']}

y['machines'].remove('bar')     #修改某个值(原地修改,而不是替换),原始字典x变量也会改变

print y

#{'username': 'mlh', 'machines': ['foo', 'baz']}

print x

#{'username': 'admin', 'machines': ['foo', 'baz']}

#避免这个问题的一种方法就是使用深复制,复制其包含的所有值。可以使用copy模块的deepcopy函数来完成操作。


#deepcopy

#深复制

from copy import deepcopy       #导入copy模块的deepcopy函数

d = {}

d['names'] = ['Alfred', 'Bertrand']

c = d.copy()

dc = deepcopy(d)

d['names'].append('Clive')     #原始字典变量d增加值

print d

#{'names': ['Alfred', 'Bertrand', 'Clive']}

print c                         #浅复制会一起增加

#{'names': ['Alfred', 'Bertrand', 'Clive']}

print dc                        #深复制则不会改变

#{'names': ['Alfred', 'Bertrand']}


#fromkeys

#给定的键建立新字典,每个键对应一个默认值None

print {}.fromkeys(['name', 'age'])         #它首先构造空字典,然后调用fromkeys方法建立另外一个词典---有些多余。建议用dict方法

#{'age': None, 'name': None}

print dict.fromkeys(['name', 'age'])        #dict方法,效果和上面一样。建议使用。

#{'age': None, 'name': None}

print dict.fromkeys(['name', 'age'], '(unknown)')      #如果不想使用None作为默认值,也可以自己提供默认值。

#{'age': '(unknown)', 'name': '(unknown)'}


#get

#更宽松的访问字典方法,一般访问不存在的项会报错,get访问不会报错,得到None

d = {}

#print d['name']       #这样访问会报错

print d.get('name')  #get不会报错,返回None

#None

print d.get('name', 'N/A')      #也可以自定义None,改成N/A,如果键在不会替换

#N/A

d['name'] = 'Eric'

print d.get('name')           #如果键存在,get用起来和普通字典查询一样

#Eric

print d.get('name', 'N/A')     #如果键存在,不会替换

#Eric

#has_key

#检查有没键

d = {}

print d.has_key('name')     #没有键

#False

d['name'] = 'Eric'

print d.has_key('name')     #有键

#True


#items和iteritems

#items将字典所有的项以列表方法返回,列表中的每一项都表示为(键,值)队的形式。但是项在返回时并没有遵循特定的次序。

d = { 'title': 'Python Web Site', 'url': 'http://www.python.org', 'spam': 0 }

print d.items()

#[('url', 'http://www.python.org'), ('spam', 0), ('title', 'Python Web Site')]

#iteritems方法的作用大致相同,但是会返回一个迭代器对象而不是列表:

it = d.iteritems()      #返回迭代器

print it

#<dictionary-itemiterator object at 0x00000000022B2A98>

print list(it)      #转换为列表

#[('url', 'http://www.python.org'), ('spam', 0), ('title', 'Python Web Site')]


#keys和iterkeys

#keys方法将字典中的键以列表形式返回,而iterkeys则返回针对键的迭代器。

d = { 'title': 'Python Web Site', 'url': 'http://www.python.org', 'spam': 0 }

print d.keys()          #将字典中的键以列表形式返回

#['url', 'spam', 'title']

it = d.iterkeys()          #返回迭代器

print it

#<dictionary-keyiterator object at 0x00000000022C2B38>

print list(it)      #转换为列表

#['url', 'spam', 'title']


#values和itervalues

#valuse方法以列表的形式返回字典中的值,与返回键的列表不同的是,返回值的列表中可以包含重复的元素。itervalues则返回值的迭代器。

d = {}

d[1] = 1

d[2] = 2

d[3] = 3

d[4] = 1

print d.values()

#[1, 2, 3, 1]

it = d.itervalues()     #返回迭代器

print it

print list(it)      #转换为列表

#<dictionary-valueiterator object at 0x0000000002232B88>


#pop

#移除键和值

d = {'x': 1, 'y': 2}

d.pop('x')            #删除x键和值

print d

#{'y': 2}


#popitem

#随机删除

d = {'x': 1, 'y': 2 ,'z': 3}

d.popitem()           #随机删除一个,好处不用指定键,字典没有顺序概念,若想一个个移除,这个方法非常有效。

print d

#{'x': 1, 'z': 3}


#setdefault

#类似get方法,在没有键情况下可以设定相应键

d = {}

d.setdefault('name', 'N/A')

print d

#{'name': 'N/A'}

d['name'] = 'Gumby'

d.setdefault('name', 'N/A')               #有键不会替换

print d

#{'name': 'Gumby'}


#update

#一个字典更新到另一个字典

d = {

   'x': '1',

   'y': '2',

   'z': '3'

}

e = {'a': '4'}

d.update(e)

print d

#{'y': '2', 'x': '1', 'z': '3', 'a': '4'}


#涉及的函数

#dict(seq)                  用(键,值)对(或者映射和关键字参数)建立字典