Python数据结构:映射(map)——字典

dict 基础

映射——字典(Python唯一内建的映射类型):可以使用任意不可变对象标识元素,因为是不可变的,所以一般最常用 key 类型就是 string 和 tuple

1. 格式化字符串在 dict 中的应用:

应用场景:(dict 的元素多起来的时候不要遗漏逗号 ,)

people = {
'Alice':{
    'phone':'2341', # attention , missing
    'addr':'Foo drive'
    },
'Beth':{
    'phone':'9102',
    'addr':'Bar street 42'
    },
'Cecil':{
    'phone':'3158',
    'addr':'Baz avenue 90'
    }
}
labels = {
'phone':'phone number',
'addr':'address'
}

name = raw_input('Name:')
request = raw_input('Phone number (p) or address (a)?')

if request == 'p':key = 'phone'
elif request =='a':key = 'addr'

if name in people:
    print name
    print " %s's %s is %s." % (name, labels[key],people[name][key])
参考 字符串格式化(1. 字符串格式化 %——格式化字符串 % 需要放到格式化字符串的值)中所提到的,如果进行多个值的匹配,会用到tuple,见上述代码最后一行 % 后面是一个tuple。

dict 在字符串格式化中也很有用处,适用情况是 dict 的 key 必须是string:

phonebook = {'Beth':'9102', 'Alice':'2341', 'Cecil':'3258'}
str0 = "Cecil's phone number is %(Cecil)s"
print str0 % phonebook
上述代码中将格式化字符串的 转换说明符替换成为了: %(key) 的格式,显示出来的就是 key为 Cecil 的在dict 中的value

2. dict 与 list:
有人名列表和对应的电话号码列表,根据人名查找相应电话:

tel = ['2345', '8012', '1257']
name = ['Lily','Tom','Jack']
print 'Find Lily',tel[name.index('Lily')]
# dict
phonebook = {'Lily':'2345', 'Tom':'8012', 'Jack':'1257'} # attention {}
print 'Find Lily',phonebook['Lily']

a. list 变为 dict

items0 = [['name','Tomy'],['age',42]]
items1 = [['name','Tomy'],('age',42)]
items2= [('name','Tomy'),('age',42)]
print dict(items0),dict(items1),dict(items2)

d = dict(name = 'Tomy',age = 42) # there is no quote
print d

b. Convert dictionaries into lists

print list(dict)
reference:int(string), float(z)

但是这个list 只是dict 里面的 key,也就是a、b、c而没有里面的值2、1、2


——跟 sequence list 一样的是:

赋值操作——list[0] = x, dict[key] = x,只是[]里面表示的改变;

 len(list/dict) ——都是查找到一共有多少个元素,dict里面的元素是一对的,因为key相当于下标;

in 其实就不一样了——in 在 dict 里面查找的是 key 的值(而列表则是查找 value,不是下标),查找到了键,就相当于查找到了值。

因为字典中的 key 是唯一的,是任意不可变的类型,而 value 不是。数据结构很大的时候,字典优势越加明显



dict 方法

1. 遍历 dict

给出一个dictionaries以供后续操作:

dict = {'a': 2, 'b': 1, 'c': 2}

a. Keys and values in dictionaries

dict.keys() # return a list of key
dict.values() # return a list of value

The order of keys and the values will come out in the same order

使用iterkeys() 将会返回 key 的迭代器对象

使用itervalues() 将会返回 value 的迭代器对象


b. Items in dictionaries

print dict.items() # returns a list (list of tuples: key/value pair)

为了更高效的的迭代,可以使用 iteritems():

print dict.iteritems(),type(dict.iteritems()) # 返回一个迭代器对象


c. Loop in dictionaries (two method)

for key in dict:
    print key, dict[key]
key is not value, key just a label,这个打印出的循环项是 dict 中的 key,要打印出键值对必须对 dict.items() 进行循环

for item in dict.items():
    print item
上述代码将会在 每次循环打印一个 tuple,同样这个tuple将是 key/value pair,因为使用items() 这个函数将会返回一个由 tuples(key/value pair)组成的列表,在这里就相当于遍历这个列表。

当然,如果不想打印 tuple,可以采用如下方式:

for key, value in dict.items(): # or for (key, value) in dict.items():
    print key, value

也就是用tuple作为循环项遍历列表,将 key, value 加上括号就更明显了。

最后,dict 的遍历比较复杂,简单总结一下,要看清循环的对象到底是什么类型的

dict 类型的,循环出来的就是 key

dict.items(), 因为是列表,且每一项是 tuple,所以循环出来是 tuple


2. clear 清除所有元素

x = {}
y = x
x['key'] = 'value'
print y
x = {}
print y
上面的 x = {} 实际上是给 x 又建立了一个引用, 而y 的引用依旧指向原 x,所以如果要真正的清除 x 中的值,而不是将x 重新赋值一个空 dict, 只需要将 x = {} 替换为 x.clear()


3. copy 创建副本

x = {'username':'admin', 'machine':['foo', 'bar', 'baz']}
y = x.copy()
y['username'] = 'haha'
y['machine'].remove('bar')
print x
print y
这样创建的副本是:可以修改,不能替换原有值的。而如果使用 y = x 的形式,实际上并没有创建副本,两者都指向了同一个内存地址

from copy import deepcopy
d = {}
d['name'] = ['Alfred','Bertrand']

c= d.copy()
dc = deepcopy(d)

d['name'].append('Clive')

print c
print dc

d['name'] = 123
print c
print dc
print d


4. get 更安全的访问字典

people = {
'Alice':{
    'phone':'2341', # attention , missing
    'addr':'Foo drive'
    },
'Beth':{
    'phone':'9102',
    'addr':'Bar street 42'
    },
'Cecil':{
    'phone':'3158',
    'addr':'Baz avenue 90'
    }
}
labels = {
'phone':'phone number',
'addr':'address'
}

name = raw_input('Name:')
request = raw_input('Phone number (p) or address (a)?')

if request == 'p':key = 'phone'
elif request =='a':key = 'addr'

person = people.get(name,{})
label = labels.get(key, key)
result = person.get(key,'not available') # person.get(key)
print "%s's %s is %s" % (name, label,result)

if name in people:
    print name
    print " %s's %s is %s." % (name, labels[key],people[name][key])

dict.get(key,default_value),get 方法保证了安全,要是用户输入的 key 在dict 中并不存在的话,get方法就会使用 default_value 来创建一个 用户输入的 key 在 dict 中,如果第二个参数不设定,则会返回一个 None 。get() 方法会返回一个将要添加到字典的 default_value, 然后我们可以对这个default_value 进行修改——满足更多的变量需求( default_value 不确定,却又需要有一个值 ) 

girls = ['alice', 'bernice', 'clarice']
boys = ['chris', 'arnold', 'bob']
letterGirls = {}
for girl in girls:
    print letterGirls.setdefault(girl[0],[])
    letterGirls.setdefault(girl[0],[]).append(girl)
    letterGirls.get(girl[0],[]).append(girl)  # same with default
    print letterGirls

当然,如果并不想多多增加一个元素在 dict 里面,使用has_key(key) 方法判断是否存在特定的 key 也是可以的(返回一个boolean 值):

d = {}
print d.has_key('name')
d['name'] = 'Eric'
print d.has_key('name')
类似方法:setdefault()

5. pop,popitem 移除项

根据意图:指定移除 key——pop(有参数);移除任意 key(如果需要对每一个项都要进行移除操作,使用就会很有效)——popitem()

print dict.pop('a'),dict
print dict.popitem(), dict # popitem will return the remove item

popitem() 类似于 list.pop,不过list 是移除最后一个值,而 dict 没有最后一个值的概念(append也不会适用了),所以是随机移除。


6. update 更新字典指定项

假设people 字典有一项 Alice 的地址和电话更新了,那么可以这么做:

people = {
'Alice':{
    'phone':'2341', # attention , missing
    'addr':'Foo drive'
    },
'Beth':{
    'phone':'9102',
    'addr':'Bar street 42'
    },
'Cecil':{
    'phone':'3158',
    'addr':'Baz avenue 90'
    }
}

update = {
    'Alice':{
        'phone':'0010',
        'addr':'1st Avenue'
        }
}

people.update(update)
print people

update 是更新后的预期项。







你可能感兴趣的:(Python从入门到xx)