字典其实和之前的元祖和列表功能相似,都是用来储存一系列对象的。也就是一种可变容器,或者是我所比喻的革新派的菜单。
但也不是完全相同,我在之前曾经将字典称为特殊的'序列',是字典拥有序列的部分特性,但是又不符合序列的定义。
首先我们来看下字典是如何创建的:
a = {'a':1,'b':2,'c':2}
b = {}
c = dict(a=1)
print a
print b
print c
我们可以使用{} 或者dict() 来创建一个字典对象。
但字典里面写的是什么?下面我来分析一下。
首先,字典是以键值对的形式来储存对象的,即 key:value ,键和值之间用冒号分隔,而每个键值对之间用逗号分隔。
这个是时候可以联想一下序列的形式,在序列中,对象之间也是用逗号分隔的,但不同的是,序列是使用索引作为key,且索引是提取定义好的,按照一定顺序的。但是字典中,key是自定义的,相当于我们为对象起一个变量名,只不过变量名在字典的key中是以字符串的形式存在的,就像 c 中的创建方式,变量名为 a ,最终得到的键为 'a'。
那是不是字典的键就只能是字符串类型呢?并不是,我们也可以像序列一样用数字作为键。
a = {666:'scolia',}
print a
当然,为了提高代码可读性,我在只有单个对象的时候还是用了逗号。
元祖和列表也可以作为键吗?
答案是:NO!
虽说几乎所有类型的python对象都能作为键(只要该对象是可哈希的),但是一般还是以数字或者字符串最为常用。
看到这里,我们可能会想字典无非就是高级一点的列表而已,为什么又不是序列呢?
因为字典是无序的。
我们看变量 a 中的字典:
a = {'a':1,'b':2,'c':2}
我们在创建的时候明明是按一定顺序排列的,为什么输出的时候顺序却乱了?
这正是字典无序性的体现。
首先序列之所以被称为序列:正如其名,有序的、队列式的。我们在序列中逐一放入元素的时候,会自动的按照从左到右进行编号,也就是索引,而每一个索引对应一个对象。而字典却失去了索引的约束,用了自定义的键来取代,当我们在获取对象时也是用键名来获取,只要知道了键名,那么对象在字典中的哪个位置也无所谓了,所以字典是无序的,也就不能称为序列。
但我们依然可以将其想象为是一种高级的列表,只不过这个列表的索引是自定义的,无序的。
另外,当字典中的出现了同名的键会怎么办?
a = {'scolia': 1,'scolia':2,'scolia':3}
print a
就像变量命名一样,前面的都被冲突掉了。
这时又有同学问:不是说字典是无序的吗?我怎么知道谁在前谁在后?
我曾经把索引比作是特殊的变量名,只不过普通的变量名不能只是数字,而索引则是通过数字去内存取值。同理,字典里的键也可以看作是变量名,在字典里的元素打包成一个字典之前,先进行了变量的赋值操作,而对同一个变量进行多次赋值相当于切换其在内存的引用,只有最后一个赋值有效,这里也是一样的。在键值对创建的时候,按照我们写时候的顺序先进行赋值操作,然后保存在字典中,保存之后才是无序的。
那么值相同的时候是否也是同一个对象呢?
a = {'a':300,'b':300}
print id(a['a']),id(a['b'])
看来是的,和序列中的一样,也是节省内存的优化。
接下来我们就可以开始学习字典的内置方法了,首先按老规矩先使用 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 | | fromkeys(...) | dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v. | v defaults to None. | | 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 | | itervalues(...) | D.itervalues() -> an iterator over the values of D | | keys(...) | D.keys() -> list of D's keys | | pop(...) | D.pop(k[,d]) -> v, remove specified key and return the corresponding value. | If key is not found, d is returned if given, otherwise KeyError is raised | | popitem(...) | D.popitem() -> (k, v), remove and return some (key, value) pair as a | 2-tuple; but raise KeyError if D is empty. | | setdefault(...) | D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D | | update(...) | D.update([E, ]**F) -> None. Update D from dict/iterable E and F. | If E present and has a .keys() method, does: for k in E: D[k] = E[k] | If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v | In either case, this is followed by: for k in F: D[k] = F[k] | | values(...) | D.values() -> list of D's values | | viewitems(...) | D.viewitems() -> a set-like object providing a view on D's items | | viewkeys(...) | D.viewkeys() -> a set-like object providing a view on D's keys | | viewvalues(...) | D.viewvalues() -> an object providing a view on D's values | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | __hash__ = None | | __new__ = <built-in method __new__ of type object> | T.__new__(S, ...) -> a new object with type S, a subtype of T