1. 映射类型-字典
1.0
①字典是Python中唯一的映射类型,通常认为是可变的哈希表
②映射类型中的数据是无序排列的
③方法keys()、values()分别返回键、值组成的列表;items()方法可以得到键、值对应得元组组成的列表
1.1 创建字典和给字典赋值
①创建字典
>>> dict1 = {} >>> dict2 = {'name': 'earth', 'port': 80} >>> dict1, dict2 ({}, {'name': 'earth', 'port': 80}) >>> >>> # 使用内建方法 dict() 创建 >>> fdict = dict((['x', 1], ['y', 2])) >>> fdict {'y': 2, 'x': 1} >>> >>> #使用内建方法 fromkeys() 创建字典,字典中的元素具有相同的值,若未给出则默认为'None' >>> ddict = {}.fromkeys(('x', 'y'), -1) >>> ddict {'y': -1, 'x': -1} >>> >>> edict = {}.fromkeys(('foo', 'bar')) >>> edict {'foo': None, 'bar': None}
1.2 访问字典中的值
①通过循环查看键遍历循环
>>> dict2 = {'name': 'earth', 'port': 80} >>> >>> for key in dict2.keys(): ... print 'key=%s, value=%s' % (key, dict2[key]) ... key=name, value=earth key=port, value=80
②直接迭代字典访问没个值
>>> dict2 = {'name': 'earth', 'port': 80} >>> >>> for key in dict2: ... print 'key=%s, value=%s' % (key, dict2[key]) ... key=name, value=earth key=port, value=80
③得到字典中某元素的值
>>> # 类似序列类型 >>> dict2['name'] 'earth' >>> >>> print 'host %s is running on port %d' % \ ... (dict2['name'], dict2['port']) host earth is running on port 80
④访问字典中没有的数据/键,会返回'KeyError'错误
>>> dict2['server'] Traceback (most recent call last): file "<stdin>", line1, in <module> KeyError: 'server'
⑤检查字典中是否有某个键可以用字典的has_key()方法,或者'in'、'not in' 操作符。推荐使用'in'操作符
>>> 'sever' in dict2 False >>> dict2.has_key('sever') False >>> 'name' in dict2 # or dict2.has_key('server') True >>> dict2['name'] earth
⑥对字典赋值
>>> dict3 = {} >>> # 逐一添加 >>> dict3[1] = 'abc' >>> dict3['1'] = 3.14159 >>> dict3[3.2] = 'xyz' >>> dict3 {'1': 3.14159, 1: 'abc', 3.2: 'xyz'} >>> # 整体赋值 >>> dict3 = {1: 'abc', '1': 3.14, 2: 'xyz'} >>> dict3 {'1': 3.14, 1: 'abc', 2: 'xyz'}
⑦数字、字符串、元组等不可变对象可作为字典的键,列表和其他字典等可变对象不能作为字典的键
1.3 更新字典
>>> dict2['name'] = 'venus' # 更新已有条目 >>> dict2['port'] = 6969 # 更新已有条目 >>> dict2['arch'] = 'sunos5' # 增加新条目 >>> >>> print 'host %(name)s is running on port %(port)d' %dict2 host venus is running on port 6969
注:①若字典中某键已存在,则[]更新已有的值;若不存在,则创建键、值
②字典中使用格式化字符串%的优点是只用一次字典的名字,而不是每个元素都用元组参数表示
1.4 删除字典元素和字典
>>> del dict2['name'] # 删除键为"name"的条目 >>> dict2.pop('port') # 删除并返回键为'port'的条目 6969 >>> dict2.clear() # 删除dict2所以条目 >>> del dict2 # 删除整个dict字典
2. 映射类型操作符
2.1 映射类型操作符
①字典的键查找操作符'[]'既可以用于给键赋值;也可以用于从字典中取值,取键对应的值
②'in'、'not in' 检查某个键是否在字典中
3. 映射类型的内建函数和工厂函数
3.1 标准类型函数[type() str()]
①对字典调用type()方法,返回<type 'dict'>;调用str()返回字典的字符串表示
>>> dict3 = {1: 'abc', '1': 3.14, 2: 'xyz'} >>> type(dict3) <type 'dict'> >>> str(dict3) "{'1': 3.14, 1: 'abc', 2: 'xyz'}"
3.2 映射类型相关的函数
3.2.1 dict()
① dict()函数用来创建字典,若不提供参数,则生成空白字典;若给定的参数是可迭代的,则可迭代的元素必须成对出现,在每对中第一个元素是键,第二个元素是值
>>> dict(zip(('x', 'y'), (1, 2))) {'y': 2, 'x': 1} >>> dict([['x', 1], ['y', 2]]) {'y': 2, 'x': 1} >>> dict([('xy'[i-1], i) for i in range(1, 3)]) {'y': 2, 'x': 1}
②dict()可以接受字典参数或者关键字参数组成的字典。对另外一个字典对象调用dict()则会复制其内容生成新的字典,与字典内建方法copy()效果一致,更推荐使用copy()方法
>>> dict(x=1, y=2) {'y': 2, 'x': 1} >>> dict8 = dict(x=1, y=2) >>> dict8 {'y': 2, 'x': 1} >>> dict9 = dict(**dict8) # 更推荐使用 dict9 = dict8.copy() >>> dict9 {'y': 2, 'x': 1} >>> dict9 = dict8.copy() >>> dict9 {'y': 2, 'x': 1}
3.2.2 len()
对字典调用len()函数,会返回所有元素(键-值对)的数目
>>> dict2 = {'name': 'earth', 'port': 80} >>> dict2 {'name': 'earth', 'port': 80} >>> len(dict2) 2
3.2.3 hash()
将一个对象做为参数传递给 hash() 会返回这个对象的哈希值,只有对象是可哈希的,才可作为字典的键。可哈希的对象返回的值是整型,不产生错误或异常;非可哈希类型传递给hash()会产生TypeError,使用这样的键给字典赋值会产生TypeError 错误。
>>> hash([]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'list' >>> >>> dict2[{}] = 'foo' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'dict'
3.2.4 合集
4. 映射类型内建方法
4.2 详细讲解
①字典的keys()方法返回一个列表,包含字典中所有的键;字典的values()方法返回一个列表,包含字典中所有的值;items()方法返回一个包含所有(键,值)元组的列表。这些方法均用于遍历字典的键或值,且是无序的
>>> dict2 = {'name': 'earth', 'port': 80} >>> dict2.keys() ['name', 'port'] >>> >>> dict2.values() ['earth', 80] >>> >>> dict2.items() [('name', 'earth'), ('port', 80)] >>> >>> for eachkey in dict2.keys(): ... print 'dict2 key', eachkey, 'has value', dict2[eachkey] ... dict2 key name has value earth dict2 key port has value 80
②Python 2.4以后,字典新增sorted()内建函数,返回有序的迭代子,用来有序的迭代字典的键
>>> for eachkey in sorted(dict2): ... print 'dict2 key', eachkey, 'has value', dict2[eachkey] ... dict2 key name has value earth dict2 key port has value 80
③update()方法用来将一个字典A的内容添加到另一个字典B中,字典B中的键若与A中的键重复,则B中该键对应的值会被A中相应的值替换,B中不存在的条目则从A中添加进去。clear()方法则用来删除字典中所有条目
>>> dict2 = {'host': 'earth', 'port': 80} >>> dict3 = {'host': 'venus', 'server': 'http'} >>> dict2.update(dict3) >>> dict2 {'host': 'venus', 'port': 80, 'server': 'http'} >>> dict3.clear() >>> dict3 {}
④copy()返回一个浅复制的字典副本。get()方法类似于键查找操作符([]),不同在于在查找的键不存在时可以给出一个参数作为返回值,若未给出则返回None
>>> dict4 = dict2.copy() >>> dict4 {'host': 'venus', 'port': 80, 'server': 'http'} >>> dict4.get('host') 'venus' >>> dict4.get('xxx') >>> type(dict4.get('xxx')) <type 'NoneType'> >>> dict4.get('xxx', 'no such key') 'no such key'
⑤setdefault()方法检查字典中是否有某键:若有,则返回所对应的值;若不存在该键,则对此键赋值并返回该值
>>> myDict = {'host': 'earth', 'port': 80} >>> myDict.keys() ['host', 'port'] >>> myDict.items() [('host', 'earth'), ('port', 80)] >>> myDict.setdefault('port', 8070) 80 >>> myDict.setdefault('prot', 'tcp') 'tcp' >>> myDict.setdefault('prt') >>> myDict.items() [('prt', None), ('host', 'earth'), ('prot', 'tcp'), ('port', 80)]
⑥fromkeys()方法
>>> {}.fromkeys('xyz') {'y': None, 'x': None, 'z': None} >>> >>> {}.fromkeys(('love', 'honor'), True) {'love': True, 'honor': True}
5. 字典的键
5.1 不允许一个键对应多个值
每个键只能对应一个项,对某键重复赋值时,取最近或者最后的赋值
>>> dict1 = {'foo': 789, 'foo': 'xyz'} >>> dict1 {'foo': 'xyz'} >>> >>> dict1['foo'] = 123 >>> dict1 {'foo': 123}
5.2 键必须是可哈希的
所有不可变对象都是可哈希的,都可以作为字典的键;值相等的数字哈希值相同,表示他们是同一个键
5.3 例子
#!/usr/bin/env python # -*- coding:utf-8 -*- db = {} def newuser(): prompt = u'注册帐号:' while True: name = raw_input(prompt.encode('gbk')) if name in db: prompt = u'帐号已被注册,请更换一个:' continue else: break pwd = raw_input(u'输入密码:'.encode('gbk')) db[name] = pwd def olduser(): name = raw_input(u'登陆账号:'.encode('gbk')) pwd = raw_input(u'登录密码:'.encode('gbk')) passwd = db.get(name) if passwd == pwd: print u'登录成功,欢迎你',name else: print u"登录失败,帐号或密码错误" def showmenu(): prompt = u""" (N)新用户注册 (E)已有账户登录 (Q)退出 请输入相应字母做出选择:""" done = False while not done: chosen = False while not chosen: try: choice = raw_input(prompt.encode('gbk')).strip()[0].lower() except (EOFError, KeyboardInterrupt, IndexError): choice = 'q' print u'\n你选择了:【%s】' % choice if choice not in 'neq': print u"输入错误,请重试" else: chosen = True if choice == 'q': done = True if choice == 'n': newuser() if choice == 'e': olduser() if __name__ == '__main__': showmenu()
6. 集合
6.1 创建集合类型和给集合赋值
集合被创建的唯一方法是使用工厂方法set()和frozenset()
>>> s = set('cheeseshop') >>> s set(['c', 'e', 'h', 'o', 'p', 's']) >>> t = frozenset('bookshop') >>> t frozenset(['b', 'h', 'k', 'o', 'p', 's']) >>> type(s) <type 'set'> >>> type(t) <type 'frozenset'> >>> len(s) 6 >>> len(s) == len(t) True >>> s == t False
6.2 访问集合中的值
可以迭代遍历查看集合中的成员,用 in 判断某元素是否是集合成员
>>> 'k' in s False >>> 'k' in t True >>> 'c' not in t True >>> for i in s: ... print i ... c e h o p s
6.3 更新集合
>>> s.add('z') >>> s set(['c', 'e', 'h', 'o', 'p', 's', 'z']) >>> s.update('pypi') >>> s set(['c', 'e', 'i', 'h', 'o', 'p', 's', 'y', 'z']) >>> s.remove('z') >>> s set(['c', 'e', 'i', 'h', 'o', 'p', 's', 'y']) >>> s -= set('pypi') >>> s set(['c', 'e', 'h', 'o', 's']) >>> t.add('z') # 更新不可变集合,会引发异常 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'frozenset' object has no attribute 'add'
7. 集合类型操作符
7.1 集合类型操作符
①联合(|)和集合的OR等价,其实就是集合的并集。等价于方法union()
>>> s | t set(['c', 'b', 'e', 'h', 'k', 'o', 'p', 's'])
②交集(&)类似于集合的and,等价方法是 intersection()
>>> s & t set(['h', 's', 'o'])
③两个集合(s、t)的差补或者相对补集是指存在一个集合c,该集合中的元素只属于集合s,不属于集合t。等价方法是difference()
>>> s - t set(['c', 'e'])
④两个集合(s和t)的对称差分是指存在一个集合C,该集合中的元素只属于s或者t中的一个,而不能是两者的交集。等价方法是 symmetric_difference()
>>> s ^ t set(['b', 'e', 'k', 'c'])
⑤若操作符左右两个集合的类型相同,都是可变集合或不可变集合,则产生的结果类型也是可变集合或不可变集合。若连个集合类型不同,则结果类型与操作符左边的集合类型相同
>>> t | s frozenset(['c', 'b', 'e', 'h', 'k', 'o', 'p', 's']) >>> t ^ s frozenset(['c', 'b', 'e', 'k']) >>> t - s frozenset(['k', 'b'])
⑥加号(+)不是集合类型操作符
>>> s + t Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'set' and 'frozenset'
7.2 仅用于可变集合的集合类型操作符
① |= 操作符和update()方法等价,用于向已存在的集合中添加成员
>>> s = set('cheeseshop') >>> u = frozenset(s) >>> s |= set('pypi') >>> s set(['c', 'e', 'i', 'h', 'o', 'p', 's', 'y'])
② &= 操作符保留与新集合的交集,等价于 intersection_update() 方法
>>> s = set(u) >>> s &= set('shop') >>> s set(['h', 's', 'o', 'p'])
③ -= 操作's -= t'对s和t进行差更新,返回集合s去除集合t的元素后剩余元素组成的集合,等价于difference_update()方法
>>> s = set(u) >>> s -= set('shop') >>> s set(['c', 'e'])
④ ^= 操作 's ^= t' 对s和t进行对称差分更新,返回s和t的交集在s和t的并集中的补集,等价于symmetric_difference_update()方法
>>> s = set(u) >>> t = frozenset('bookshop') >>> s ^= t >>> s set(['c', 'b', 'e', 'k'])
8. 内建函数
8.1 标准类型函数
把集合作为参数传递给内建函数len(), 返回集合的元素个数
>>> s = set(u) >>> s set(['p', 'c', 'e', 'h', 's', 'o']) >>> len(s) 6
8.2 集合类型工厂函数
set()和frozenset()分别用来生产可变集合和不可变集合。不提供参数默认生产空白集合;若提供参数,则参数必须是可迭代的,如序列、字典或文件等
>>> set() set([]) >>> set([]) set([]) >>> set(()) set([]) >>> set('shop') set(['h', 's', 'o', 'p']) >>> frozenset(['foo', 'bar']) frozenset(['foo', 'bar']) >>> >>> f = open('numbers', 'w') >>> for i in range(5): ... f.write('%d\n' % i) ... >>> f.close() >>> f = open('numbers', 'r') >>> set(f) set(['0\n', '3\n', '1\n', '4\n', '2\n']) >>> f.close()