字典其实和以前的元祖和列表功能类似,都是用来储存一系列对象的。也就是一种可变容器,或者是我所比喻的革新派的菜单。html
但也不是彻底相同,我在以前曾经将字典称为特殊的'序列',是字典拥有序列的部分特性,可是又不符合序列的定义。python
首先咱们来看下字典是如何建立的:app
a = {'a':1,'b':2,'c':2} b = {} c = dict(a=1) print a print b print c
咱们可使用{} 或者dict() 来建立一个字典对象。ide
但字典里面写的是什么?下面我来分析一下。函数
首先,字典是以键值对的形式来储存对象的,即 key:value ,键和值之间用冒号分隔,而每一个键值对之间用逗号分隔。学习
这个是时候能够联想一下序列的形式,在序列中,对象之间也是用逗号分隔的,但不一样的是,序列是使用索引做为key,且索引是提取定义好的,按照必定顺序的。可是字典中,key是自定义的,至关于咱们为对象起一个变量名,只不过变量名在字典的key中是以字符串的形式存在的,就像 c 中的建立方式,变量名为 a ,最终获得的键为 'a'。优化
那是否是字典的键就只能是字符串类型呢?并非,咱们也能够像序列同样用数字做为键。ui
a = {666:'scolia',} print a
固然,为了提升代码可读性,我在只有单个对象的时候仍是用了逗号。this
元祖和列表也能够做为键吗?spa
答案是: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
按照其功能可分为:
1.大于、小于、等于等比较运算符
2.成员判断
3.内置函数相关的(参考这里)
4.增删改查相关操做
1.比较运算符
由于字典不是序列了,因此就不能像序列同样按照索引逐个打擂台了。
不过大小的比较规则仍是同样的,只是上场的顺序未知而已。
那到底比较的时候顺序是怎么样的,看下面的例子。
a = {'a':1,'b':2,'c':3} for x in a: print x
咱们使用for循环来看看比较时的顺序,能够看出,顺序是无可预估的,虽然这里只有三个键值对,貌似有必定的规律,可是一旦里面的对象多起来,就得不出规律了,并且不可能每次比较的时候都要本身看一下里面是怎么比的,那样实在太累,因此咱们得出一个结论:少用字典间的比较,要比较用序列去。
另外这里补充一点:当咱们使用for循环时,咱们获得的是键名,若是咱们要取到值怎么办?能够像下面这样写:
a = {'a':1,'b':2,'c':3} for x in a: print a[x]
固然还有其余写法,看完内置方法后本身总结吧。
2.成员判断
1. in
在序列中判断里面有没有某个元素时使用的是 in ,但细心的同窗会发现,在帮助文档中并无出现 in ,是否是in不能用了呢?
看下面这个例子:
a = {'a':1,'b':2, 3:30} b = 2 print b in a print 2 in a print 'b' in a print 3 in a
还可使用,可是这里 in 只能判断字典里是否有哪一个键,而不是键对应的值。
2. D.has_key(k) -> True if D has a key k, else False
和 in 同样,判断里面是否有某个键,返回布尔值。
a = {'a':1,'b':2, 3:30} print a.has_key('b') print a.has_key(3)
3. D.__contains__(k) -> True if D has a key k, else False
判断是否有某个键,和上面的同样,就很少说明了。
4.判断字典里面是否有某个对象。
字典中并无内置的方法能直接判断,可是咱们能够本身写一个。
a = {'a':1,'b':2, 3:30} b = 30 c = a.values() #返回一个由字典的值组成的列表 print c #一样咱们没法预估字典里的顺序 print b in c
咱们转了一个弯,这就要考验思惟的灵活性了。
3.增
1. x.__setitem__(i, y) <==> x[i]=y
这个和列表中的不一样,列表的这个写法是修改元素,若是给的索引不存在是会报错的。但在字典中,这个方法除了能够用来修改元素以外,若是给定的键不存在,则会在字典中建立这个键值对。
a = {'a':1,'b':2, 3:30} a['scolia'] = 'good' print a
2. dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v. v defaults to None.
这个方法用于建立新的字典对象,我这里将其归类到这里。
其中,S 为一个键的序列,v为值,将为S所指定的全部键设置同一个值,默认为None。
a = dict.fromkeys(('scolia'),123) b = dict.fromkeys(('scolia',)) print a print b
注意S的写法,这就是为何在元祖只有一个元素的时候必定要加一个逗号,不然解释器会将其看成传参,将字符串传进去,而字符串也是一个序列,因此没一个字符都被当作一个键,就形成了a的输出了。将S写成一个列表就不会有这样的错误,但元祖消耗的资源少,具体选择看我的。
a = dict.fromkeys(['scolia'],123) print a
a = {'scolia': 1,'good':1,1:0} print a.fromkeys(('k'),123) print a
这里很特殊,建立的对象并无添加到原字典中,而是所为一个返回值。
3. D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
这是一个集查询、修改、增长键值对的方法。
a = dict.fromkeys(['scolia'],123) print a.setdefault('s',123) print a
这里解释这个方法的细节:首先k是必须的参数,若是只给k一个参数,则d默认为None,也能够指定d的值。
a = dict.fromkeys(['scolia'],123) print a.setdefault('scolia') print a.setdefault('s') print a
其执行顺序为:
1.先用给定的k看看里面有没有对应的键,有就返回这个键的值。
2.若是没有k这个键,则建立这个键,而后用d做为其值,若是d没给就默认为None(空对象)。
4.删
1. del x[y]
用del关键字删除对象,在列表中讲过,只不过y从索引变成了键名。这里再也不重复。
2. D.clear() -> None. Remove all items from D.
删除整个字典里的元素,返回值为None。
a ={'scolia':123} print a.clear() print a
不须要传参,但要注意就算清空了字典里的因此元素,最后获得的仍是一个空字典,而不是空对象None。
3. D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
删除指定的键值对,并返回相应的值。若是没找到键返回d,若连d都没给,则触发KeyError错误。
a ={'scolia':123,123:321} print a.pop(123) print a.pop(666,'没找到') print a.pop(999)
4. D.popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple; but raise KeyError if D is empty.
删除字典中的第一个元素,并将其按一个元祖返回,若是字典为空则触发KeyError错误
a ={'scolia':123,123:321,555:777} print a print a.popitem() print a
但仍是那句话,字典中元素的顺序是未知的,谁知道第一个是什么,因此多配合迭代循环使用,逐个删除掉。
5.查
1. D.keys() -> list of D's keys
返回一个由键组成的列表
a ={'scolia':123,123:321,555:777} print a.keys()
2. D.values() -> list of D's values
返回一个由值组成的列表
a ={'scolia':123,123:321,555:777} print a.values()
3. D.items() -> list of D's (key, value) pairs, as 2-tuples
返回一个由键值组成的元祖的列表。
a ={'scolia':123,123:321,555:777} print a.items()
4. D.iterkeys() -> an iterator over the keys of D
返回一个包含全部键的迭代对象
a ={'scolia':123,123:321,555:777} b = a.iterkeys() for x in b: print x
5. D.itervalues() -> an iterator over the values of D
返回一个包含全部值的迭代对象,原理同上,再也不详细说明。
6. D.iteritems() -> an iterator over the (key, value) items of D
返回一个包含键值对元祖的迭代对象,同理。另外注意下元祖的迭代循环技巧。
7. D.viewkeys() -> a set-like object providing a view on D's keys
返回一个键的相似集合的对象。集合的做用是去除重复,但字典对于键的重复已经有相应处理,感受意义不大。
a = {'scolia': 1,'scolia':2,1:123} print a.viewkeys() print type(a.viewkeys())
8. D.viewvalues() -> an object providing a view on D's values
返回一个值的视图对象,注意不是集合对象,没有去重做用。
a = {'scolia': 1,'good':1,1:123} print a.viewvalues() print type(a.viewvalues())
9. D.viewitems() -> a set-like object providing a view on D's items
返回一个由键和值组成的元祖的类集合对象。
a = {'scolia': 1,'good':1,1:123} print a.viewitems() print type(a.viewitems())
一样感受意义不大,缘由同上。
6.改
1. x[i]=y
和列表中的相似,只是 i 不是索引而是键名,当键名不存在时,就至关于新增键值对了。这里不重复说明了。
2. D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
上面讲过了,再也不重复
3. D.update([E, ]**F) -> None.
从字典或可迭代对象E和F中,更新元素到字典D中。这里其实也能够归类到增长对象那里去,但字典的增操做和改操做其实不少方法是能够相通的,这里就放到这里了,让这里看起来不会太单薄。
这里的**F的写法实际上是解决冗余参数的写法,详细咱们会在函数中讲。
当E .key() 有方法时。
for k in E: D[k] = E[k]
即当E也是字典时,咱们能够将一个字典添加到另外一个字典中:
a = {'scolia': 1,'good':1} b = {'scolia':2, 666:999} a.update(b) print a
print b
a中的同名键会被b的覆盖掉,且不会影响b自己。
当E没有.key()方法时。
for (k, v) in E: D[k] = v
即E为二元元祖序列,以二元元祖中的第一个元素为键,第二个元素为值,添加到字典中。
a = {'scolia': 1,'good':1,1:0} b = [('a',123),('b',321),(1,1)] a.update(b) print a
所谓二元元祖序列,即里面放多个元祖,每一个元祖只有两个元素,而其外层为序列,元祖、列表都行。
注意:有些同窗在学完函数后可能会纠结,**F其实也算是一个字典,那我传进去的字典到底是传给了谁?
首先**F是处理冗余参数的,要想有做用,首先参数要超过须要的,而当咱们传一个字典或其余对象的时候,是传给了E,当传多个对象的时候,多出来的就到了**F中了,而**F中的对象这里并无作处理,就至关于多出来的就扔到垃圾桶里去了。