8. 集合与字典

1.集合

1.1 set与frozenset

	set无序排序且不重复,是可变的,有add(),remove()等方法。既然是可变的,所以它不存在
哈希值。基本功能包括关系测试和消除重复元素. 集合对象还支持union(联合), intersection(交集), 
difference(差集)和sysmmetric difference(对称差集)等数学运算. 
	sets 支持 x in set, len(set),和 for x in set。作为一个无序的集合,sets不记录元素位置或者
插入点。因此,sets不支持 indexing, 或其它类序列的操作。frozenset是冻结的集合,它是不可变的,存在
哈希值,好处是它可以作为字典的key,也可以作为其它集合的元素。缺点是一旦创建	便不能更改,没有
add,remove方法。

1.2 集合的创建

	set()frozenset()工厂函数分别用来生成可变和不可变的集合。如果不提供任何参数,默认会生成空
集合。如果提供一个参数,则该参数必须是可迭代的,即,一个序列,或迭代器,或支持迭代的一个对象,例
如:一个列表或一个字典。
>>> s=set('cheeseshop')  使用工厂方法创建
>>> s
{'h', 'c', 'o', 's', 'e', 'p'}
>>> type(s)
<type 'set'>

>>> s={'chessseshop','bookshop'}
直接创建,类似于list[]dict{},不同于dict的是其中的值,set会将其中的元素转换为元组
>>> s
{'bookshop', 'chessseshop'}
>>> type(s)
<type 'set'>

不可变集合创建:
>>> t=frozenset('bookshop')
>>> t
frozenset({'h', 'o', 's', 'b', 'p', 'k'})

1.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'])
>>> del s  #删除集合

只有可变集合能被修改。试图修改不可变集合会引发异常。
>>> t.add('z')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'frozenset' object has no attribute 'add'

1.4 成员关系 (in, not in)

>>> 'k' in s
False
>>> 'k' in t
True
>>> 'c' not in t
True

1.5 集合等价/不等价

>>> s == t
False
>>> s != t
True
>>> u = frozenset(s)
>>> s == u
True
>>> set('posh') == set('shop')
True

1.6 子集/超集

>>> set('shop') < set('cheeseshop')
True
>>> set('bookshop') >= set('shop')
True

1.7 遍历访问集合中的值(可变集合和非可变都支持)

>>> s=set('cheeseshop')
>>> s
{'h', 'c', 'o', 's', 'e', 'p'}
>>> for i in s:
    print(i)    
h
c
o
s
e
p


>>> t=frozenset('bookshop')
>>> t
frozenset({'h', 'o', 's', 'b', 'p', 'k'})
>>> for i in t:
    print(i)    
h
o
s
b
p
k

1.8 集合类型操作符(所有的集合类型)

1.联合( | )
	两个集合的联合是一个新集合,该集合中的每个元素都至少是其中一个集合的成员,即,属于两个集合其中
之一的成员。联合符号有一个等价的方法,union().
>>> s | t
set(['c', 'b', 'e', 'h', 'k', 'o', 'p', 's'])

2.交集( & )
	你可以把交集操作比做集合的 AND(或合取)操作。两个集合的交集是一个新集合,该集合中的每个元素同时
是两个集合中的成员,即,属于两个集合的成员。交集符号有一个等价的方法,intersection()
>>> s & t
set(['h', 's', 'o', 'p']

3.差补/相对补集()
	两个集合(s 和 t)的差补或相对补集是指一个集合 C,该集合中的元素,只属于集合 s,而不属于集合 t。
差符号有一个等价的方法,difference().
>>> s - t
set(['c', 'e'])	

4.对称差分( ^ )
	和其他的布尔集合操作相似, 对称差分是集合的 XOR(又称"异或 ").两个集合(s 和 t)的对称差分是指
另外一个集合 C,该集合中的元素,只能是属于集合 s 或者集合 t的成员,不能同时属于两个集合。对称差分
有一个等价的方法,symmetric_difference().
>>> s ^ t
set(['k', 'b', 'e', 'c'])

5.混合集合类型操作
	上面的示例中,左边的 s 是可变集合,而右边的 t 是一个不可变集合. 注意上面使用集合操作运算符
所产生的仍然是可变集合,但是如果左右操作数的顺序反过来,结果就不一样了:
>>> t | s
frozenset(['c', 'b', 'e', 'h', 'k', 'o', 'p', 's'])
>>> t ^ s
frozenset(['c', 'b', 'e', 'k'])
>>> t - s frozenset(['k', 'b'])
	如果左右两个操作数的类型相同, 既都是可变集合或不可变集合, 则所产生的结果类型是相同的,但如果
左右两个操作数的类型不相同(左操作数是 set,右操作数是 frozenset,或相反情况),则所产生的结果类型
与左操作数的类型相同。

1.9 可变集合类型的方法

s.update(t) 				用 t 中的元素修改 s, 即,s 现在包含 s 或 t 的成员
s.intersection_update(t) 	s 中的成员是共同属于 s 和 t 的元素。
s.difference_update(t) 		s 中的成员是属于 s 但不包含在 t 中的元素
s.symmetric_difference_update(t) 	s 中的成员更新为那些包含在 s 或 t 中,但不 是 s
和 t 共有的元素
s.add(obj) 					在集合 s 中添加对象 obj
s.remove(obj) 				从集合 s 中删除对象 obj;如果 obj 不是集合 s 中的元素
						(obj notin s),将引发 KeyError 错误
s.discard(obj) 				如果 obj 是集合 s 中的元素,从集合 s 中删除对象 obj;
s.pop() 					删除集合 s 中的任意一个对象,并返回它
s.clear() 					删除集合 s 中的所有元素

1.10 集合类型操作符、函数和方法

函数/方法名 等价运算符 说明
所有集合类型:
len(s) 					集合基数: 集合 s 中元素的个数
set([obj])		可变集合工厂函数; obj 必须是支持迭代的,由 obj 中的元素创建集合,否则创建一个空
				集合
frozenset([obj]) 		不可变集合工厂函数; 执行方式和 set()方法相同,但它返回的是不可变集合
obj in s 				成员测试:obj 是 s 中的一个元素吗?
obj not in s 			非成员测试:obj 不是 s 中的一个元素吗?
s == t 					等价测试: 测试 s 和 t 是否具有相同的元素?
s != t 					不等价测试:==相反
s < t 					(严格意义上)子集测试; s != t 而且 s 中 所 有的元素都是 t 的成员
s.issubset(t) s <= t 	子集测试(允许不严格意义上的子集): s 中所有的元素都是 t 的成员
s > t 					(严格意义上)超集测试: s != t 而且 t 中所有的元素都是 s 的成员
s.issuperset(t) s >= t 	超集测试(允许不严格意义上的超集): t 中所有的元素都是 s 的成员
s.union(t) 				s | t 合并操作: s 或 t 中的元素
s.intersec- tion(t) 	s & t 交集操作: s 和 t 中的元素
s.difference(t) 		s - t 差分操作: s 中的元素,而不是 t 中的元素
s.symmetric_difference(t)	s ^ t 对称差分操作:s 或 t 中的元素,但不是 s 和 t 共有的元素
s.copy() 				复制操作:返回 s 的(浅复制)副本


仅用于可变集合:
s.update(t) 				s |= t (Union) 修改操作: 将 t 中的成员添加 s
s.intersection_update(t) 	s &= t 交集修改操作: s 中仅包括 s 和 t 中共有的成员
s.difference_update(t) 		s -= t 差修改操作: s 中包括仅属于 s 但不属于 t 的成员
s.symmetric_difference_update(t)  s ^= t 对称差分修改操作: s 中包括仅属于 s 或仅属于 t 的成员
s.add(obj) 					加操作: 将 obj 添加到 s
s.remove(obj) 				删除操作: 将 obj 从 s 中删除;如果 s 中不存在obj,将引发 KeyError
s.discard(obj) 				丢弃操作: remove() 的 友 好 版 本 - 如果 s 中存在 obj,从 s 中删除
s.pop() 					Pop 操作: 移除并返回 s 中的任意一个元素
s.clear() 					清除操作: 移除 s 中的所有元素

2. 字典

	Python字典是另一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。dict全称dictionary,
在其他语言中也称为map,字典是另 一种可变容器模型,且可存储任意类型对象。具有极快的查找速度。

2.1 字典的用途

	下面是Python字典的一些用途:
 表示棋盘的状态,其中每个键都是由坐标组成的元组;
 存储文件修改时间,其中的键为文件名;
 数字电话/地址簿。
假设有如下名单:
>>> names = ['Alice', 'Beth', 'Cecil', 'Dee-Dee', 'Earl']
如果要创建一个小型数据库,在其中存储这些人的电话号码,该如何办呢?一种办法是再创
建一个列表。假设只存储四位的分机号,这个列表将类似于:
>>> numbers = ['2341', '9102', '3158', '0142', '5551']
创建这些列表后,就可像下面这样查找Cecil的电话号码:
>>> numbers[names.index('Cecil')]
'3158'
这可行,但不太实用。实际上,你希望能够像下面这样做:
>>> phonebook['Cecil']
'3158'
如何达成这个目标呢?只要 phonebook 是个字典就行了。

2.2 创建和使用字典

	字典以类似于下面的方式表示:
	phonebook = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
	字典由键及其相应的值组成,这种键值对称为项(item)。在前面的示例中,键为名字,而值为电话号码。每个键与其值之间都用
冒号( : )分隔,项之间用逗号分隔,而整个字典放在花括号内。空字典(没有任何项)用两个花括号表示,类似于下面这样: {} 。

注意 :在字典(以及其他映射类型)中,键必须是独一无二的,而字典中的值无需如此。

2.2.1 函数dict

可使用函数 dict从其他映射(如其他字典)或键值对序列创建字典。
>>> items = [('name', 'Gumby'), ('age', 42)]
>>> d = dict(items)
>>> d
{'age': 42, 'name': 'Gumby'}
>>> d['name']
'Gumby'
还可使用关键字实参来调用这个函数,如下所示:
>>> d = dict(name='Gumby', age=42)
>>> d
{'age': 42, 'name': 'Gumby'}
'''
	尽管这可能是函数 dict 最常见的用法,但也可使用一个映射实参来调用它,这将创建一个字典,其中包含指定映射中的所有项。
像函数 list 、 tuple 和 str 一样,如果调用这个函数时没有提供任何实参,将返回一个空字典。从映射创建字典时,如果该映射
也是字典(毕竟字典是Python中唯一的内置映射类型),可不使用函数 dict ,而是使用字典方法 copy ,这将在后面介绍。
'''

2.2.2 基本字典操作

	字典的基本行为在很多方面都类似于序列。
 len(d) 返回字典 d 包含的项(键值对)数。
 d[k] 返回与键 k 相关联的值。
 d[k] = v 将值 v 关联到键 k 。
 del d[k] 删除键为 k 的项。
 k in d 检查字典 d 是否包含键为 k 的项。

	虽然字典和列表有多个相同之处,但也有一些重要的不同之处。
 键的类型:字典中的键可以是整数,但并非必须是整数。字典中的键可以是任何不可变的类型,如浮点数(实数)、字符串或元组。
 自动添加:即便是字典中原本没有的键,也可以给它赋值,这将在字典中创建一个新项。然而,如果不使用 append 或其他类似的
	方法,就不能给列表中没有的元素赋值。
 成员资格:表达式 k in d (其中 d 是一个字典)查找的是键而不是值,而表达式 v in l (其中 l 是一个列表)查找的是值而不是
	索引。这看似不太一致,但你习惯后就会觉得相当自然。毕竟如果字典包含指定的键,检查相应的值就很容易。
	前述第一点(键可以是任何不可变的类型)是字典的主要优点。第二点也很重要,下面的示例说明了这种差别:
>>> x = []
>>> x[42] = 'Foobar'
Traceback (most recent call last):
	File "<stdin>", line 1, in ?
IndexError: list assignment index out of range
>>> x = {}
>>> x[42] = 'Foobar'
>>> x
{42: 'Foobar'}
'''
	首先,我尝试将字符串 'Foobar' 赋给一个空列表中索引为42的元素。这显然不可能,因为没有这样的元素。要让这种操作可行,
初始化 x 时,必须使用 [None] * 43 之类的代码,而不能使用 [] 。然而,接下来的尝试完全可行。这次我将 'Foobar' 赋给一个
空字典的键42;如你所见,这样做一点问题都没有:在这个字典中添加了一个新项,我得逞了。
'''1:字典示例
# 一个简单的数据库
# 一个将人名用作键的字典。每个人都用一个字典表示,
# 字典包含键'phone'和'addr',它们分别与电话号码和地址相关联
people = {
    'Alice': {
    'phone': '2341',
    'addr': 'Foo drive 23'
    },
    'Beth': {
    'phone': '9102',
    'addr': 'Bar street 42'
    },
    'Cecil': {
    'phone': '3158',
    'addr': 'Baz avenue 90'
    }
}
# 电话号码和地址的描述性标签,供打印输出时使用
labels = {
'phone': 'phone number',
'addr': 'address'
}
name = input('Name: ')
# 要查找电话号码还是地址?
request = input('Phone number (p) or address (a)? ')
# 使用正确的键:
if request == 'p': key = 'phone'
if request == 'a': key = 'addr'
# 仅当名字是字典包含的键时才打印信息:
if name in people: print("{}'s {} is {}.".format(name, labels[key], people[name][key]))
这个程序的运行情况类似于下面这样:
Name: Beth
Phone number (p) or address (a)? p
Beth's phone number is 9102.

2.2.3 字典方法

	与其他内置类型一样,字典也有方法。字典的方法很有用,但其使用频率可能没有列表和字符串的方法那样高。你可大致浏览,
了解字典提供了哪些方法,等需要使用特定方法时再回过头来详细研究其工作原理。

1. clear
	方法 clear 删除所有的字典项,这种操作是就地执行的(就像 list.sort 一样),因此什么都不返回(或者说返回 None )。
>>> d = {}
>>> d['name'] = 'Gumby'
>>> d['age'] = 42
>>> d
{'age': 42, 'name': 'Gumby'}
>>> returned_value = d.clear()
>>> d
{}
>>> print(returned_value)
None

这为何很有用呢?我们来看两个场景。下面是第一个场景:
>>> x = {}
>>> y = x
>>> x['key'] = 'value'
>>> y
{'key': 'value'}
>>> x = {}
>>> y
{'key': 'value'}
下面是第二个场景:
>>> x = {}
>>> y = x
>>> x['key'] = 'value'
>>> y
{'key': 'value'}
>>> x.clear()
>>> y
{}
	在这两个场景中, x 和 y 最初都指向同一个字典。在第一个场景中,我通过将一个空字典赋给 x 来“清空”它。这对 y 没有任何影响,
它依然指向原来的字典。这种行为可能正是你想要的,但要删除原来字典的所有元素,必须使用 clear 。如果这样做, y 也将是空的,如第
二个场景所示。

2. copy
	方法 copy 返回一个新字典,其包含的键值对与原来的字典相同(这个方法执行的是浅复制,因为值本身是原件,而非副本)。
>>> x = {'username': 'admin', 'machines': ['foo', 'bar', 'baz']}
>>> y = x.copy()
>>> y['username'] = 'mlh'
>>> y['machines'].remove('bar')
>>> y
{'username': 'mlh', 'machines': ['foo', 'baz']}
>>> x
{'username': 'admin', 'machines': ['foo', 'baz']}
	如你所见,当替换副本中的值时,原件不受影响。然而,如果修改副本中的值(就地修改而不是替换),原件也将发生变化,因为原件
指向的也是被修改的值(如这个示例中的 'machines'列表所示)。
	为避免这种问题,一种办法是执行深复制,即同时复制值及其包含的所有值,等等。为此,可使用模块 copy 中的函数 deepcopy 。
>>> from copy import deepcopy
>>> d = {}
>>> d['names'] = ['Alfred', 'Bertrand']
>>> c = d.copy()
>>> dc = deepcopy(d)
>>> d['names'].append('Clive')
>>> c
{'names': ['Alfred', 'Bertrand', 'Clive']}
>>> dc
{'names': ['Alfred', 'Bertrand']}

3. fromkeys
	方法 fromkeys 创建一个新字典,其中包含指定的键,且每个键对应的值都是 None>>> {}.fromkeys(['name', 'age'])
{'age': None, 'name': None}
	这个示例首先创建了一个空字典,再对其调用方法 fromkeys 来创建另一个字典,这显得有点多余。你可以不这样做,而是直接对 dict 
>>> dict.fromkeys(['name', 'age'])
{'age': None, 'name': None}
如果你不想使用默认值 None ,可提供特定的值。
>>> dict.fromkeys(['name', 'age'], '(unknown)')
{'age': '(unknown)', 'name': '(unknown)'}

4. get
	方法 get 为访问字典项提供了宽松的环境。通常,如果你试图访问字典中没有的项,将引发错误。
>>> d = {}
>>> print(d['name'])
Traceback (most recent call last):
File "<stdin>", line 1, in ?
KeyError: 'name'
而使用 get 不会这样:
>>> print(d.get('name'))
None
如你所见,使用 get 来访问不存在的键时,没有引发异常,而是返回 None 。你可指定“默认”
值,这样将返回你指定的值而不是 None>>> d.get('name', 'N/A')
'N/A'
如果字典包含指定的键, get 的作用将与普通字典查找相同。
>>> d['name'] = 'Eric'
>>> d.get('name')
'Eric'2:
people = {
    'Alice': {
    'phone': '2341',
    'addr': 'Foo drive 23'
    },
    'Beth': {
    'phone': '9102',
    'addr': 'Bar street 42'
    },
    'Cecil': {
    'phone': '3158',
    'addr': 'Baz avenue 90'
    }
}
# 一个使用get()的简单数据库
# 在这里插入代码清单4-1中的数据库(字典people)
labels = {
    'phone': 'phone number',
    'addr': 'address'
}
name = input('Name: ')
# 要查找电话号码还是地址?
request = input('Phone number (p) or address (a)? ')
# 使用正确的键:
key = request # 如果request既不是'p'也不是'a'
if request == 'p': key = 'phone'
if request == 'a': key = 'addr'
# 使用get提供默认值
person = people.get(name, {})
label = labels.get(key, key)
result = person.get(key, 'not available')
print("{}'s {} is {}.".format(name, label, result))
下面是这个程序的运行情况。注意到 get 提高了灵活性,让程序在用户输入的值出乎意料时也能妥善处理。
Name: Gumby
Phone number (p) or address (a)? batting average
Gumby's batting average is not available.

5. items
	方法 items 返回一个包含所有字典项的列表,其中每个元素都为 (key, value) 的形式。字典项在列表中的排列顺序不确定。
>>> d = {'title': 'Python Web Site', 'url': 'http://www.python.org', 'spam': 0}
>>> d.items()
dict_items([('title', 'Python Web Site'), ('url', 'http://www.python.org'), ('spam', 0)])
	返回值属于一种名为字典视图的特殊类型
>>> it = d.items()
>>> len(it)
3
>>> ('spam', 0) in it
True
	视图的一个优点是不复制,它们始终是底层字典的反映,即便你修改了底层字典亦如此。
>>> d['spam'] = 1
>>> ('spam', 0) in it
False
>>> d['spam'] = 0
>>> ('spam', 0) in it
True
	然而,如果你要将字典项复制到列表中(在较旧的Python版本中,方法 items 就是这样做的),可自己动手做。
>>> list(d.items())
[('spam', 0), ('title', 'Python Web Site'), ('url', 'http://www.python.org')]

6. keys
	方法 keys 返回一个字典视图,其中包含指定字典中的键。
7. pop
	方法 pop 可用于获取与指定键相关联的值,并将该键值对从字典中删除。
>>> d = {'x': 1, 'y': 2}
>>> d.pop('x')
1
>>> d
{'y': 2}

8. popitem
	方法 popitem 类似于 list.pop ,但 list.pop 弹出列表中的最后一个元素,而 popitem 随机地弹出一个字典项,因为字典项的顺序
是不确定的,没有“最后一个元素”的概念。如果你要以高效地方式逐个删除并处理所有字典项,这可能很有用,因为这样无需先获取键列表。
>>> d = {'url': 'http://www.python.org', 'spam': 0, 'title': 'Python Web Site'}
>>> d.popitem()
('url', 'http://www.python.org')
>>> d
{'spam': 0, 'title': 'Python Web Site'}
	虽然 popitem 类似于列表方法 pop ,但字典没有与 append (它在列表末尾添加一个元素)对应的方法。这是因为字典是无序的,
类似的方法毫无意义。

9. setdefault
	方法 setdefault 有点像 get ,因为它也获取与指定键相关联的值,但除此之外, setdefault还在字典不包含指定的键时,在字典
中添加指定的键值对。
>>> d = {}
>>> d.setdefault('name', 'N/A')
'N/A'
>>> d
{'name': 'N/A'}
>>> d['name'] = 'Gumby'
>>> d.setdefault('name', 'N/A')
'Gumby'
>>> d
{'name': 'Gumby'}
	如你所见,指定的键不存在时, setdefault 返回指定的值并相应地更新字典。如果指定的键存在,就返回其值,并保持字典不变。
与 get 一样,值是可选的;如果没有指定,默认为 None>>> d = {}
>>> print(d.setdefault('name'))
None
>>> d
{'name': None}
	如你所见,指定的键不存在时, setdefault 返回指定的值并相应地更新字典。如果指定的键存在,就返回其值,并保持字典不变。
与 get 一样,值是可选的;如果没有指定,默认为 None>>> d = {}
>>> print(d.setdefault('name'))
None
>>> d
{'name': None}

10. update
	方法 update 使用一个字典中的项来更新另一个字典。
>>> d = {
...  'title': 'Python Web Site',
...  'url': 'http://www.python.org',
...  'changed': 'Mar 14 22:09:15 MET 2016'
... }	
>>> x = {'title': 'Python Language Website'}
>>> d.update(x)
>>> d
{'url': 'http://www.python.org', 'changed':
'Mar 14 22:09:15 MET 2016', 'title': 'Python Language Website'}
	对于通过参数提供的字典,将其项添加到当前字典中。如果当前字典包含键相同的项,就替换它。
	可像调用本章前面讨论的函数 dict (类型构造函数)那样调用方法 update 。这意味着调用update 时,可向它提供一个映射、
一个由键值对组成的序列(或其他可迭代对象)或关键字参数。

11. values
	方法 values 返回一个由字典中的值组成的字典视图。不同于方法 keys ,方法 values 返回的视图可能包含重复的值。
>>> d = {}
>>> d[1] = 1
>>> d[2] = 2
>>> d[3] = 3
>>> d[4] = 1
>>> d.values()
dict_values([1, 2, 3, 1])

2.3 python字典遍历的集中方法

1. 遍历key值
>>> a
{'a': '1', 'b': '2', 'c': '3'}
>>> for key in a:
       print(key+':'+a[key]) 
a:1
b:2
c:3
>>> for key in a.keys():
       print(key+':'+a[key]) 
a:1
b:2
c:3
	在使用上,for key in a和 for key in a.keys():完全等价。

2. 遍历value值
>>> for value in a.values():
       print(value)
1
2
3	

3. 遍历字典项
>>> for kv in a.items():
       print(kv)
('a', '1')
('b', '2')
('c', '3')

4. 遍历字典键值
>>> for key,value in a.items():
       print(key+':'+value)
 
a:1
b:2
c:3
>>> for (key,value) in a.items():
       print(key+':'+value)
a:1
b:2
c:3
	在使用上for key,value in a.items()for (key,value) in a.items()完全等价

3. Python的各种推导式

	推导式comprehensions(又称解析式),是Python的一种独有特性。推导式是可以从一个数据序列构建另一个新的数据序列的结构体。 
共有三种推导,在Python2和3中都有支持:

 - 列表(list)推导式
 - 字典(dict)推导式
 - 集合(set)推导式

​
一、列表推导式
​
1、使用[]生成list
​
基本格式

​[表达式 for 变量 in 列表]    或者  [表达式 for 变量 in 列表 if 条件]
​
例1:  过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母

>>> names = ['Bob','Tom','alice','Jerry','Wendy','Smith']>>> [name.upper() for name in names if len(name)>3]['ALICE', 'JERRY', 'WENDY', 'SMITH'] 

生成间隔5分钟的时间列表序列:

["%02d:%02d" %(h,m) for h in range(0, 24) for m in range(0, 60, 5)]2:(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元祖列表

>>> [(x,y) for x in range(5) if x%2==0 for y in range(5) if y %2==1][(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]3:  求M中3,6,9组成的列表

>>> M = [[1,2,3],[4,5,6],[7,8,9]]
>>> M  
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]>>> [row[2] for row in M][3, 6, 9]#或者用下面的方式  >>> [M[row][2] for row in (0,1,2)]  
[3, 6, 9]4:  求M中斜线1,5,9组成的列表


>>> M  
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]>>> [ M[i][i]  for i in range(len(M))]   即打印 M[0][0],M[1][1],M[2][2][1, 5, 9]5:  求M,N中矩阵和元素的乘积


>>> M = [[1,2,3],[4,5,6],[7,8,9]]  
>>> N = [[2,2,2],[3,3,3], [4,4,4]]>>> [M[row][col]*N[row][col] for row in range(3) for col in range(3)][2, 4, 6, 12, 15, 18, 28, 32, 36]>>> [[M[row][col]*N[row][col] for col in range(3)] for row in range(3)][[2, 4, 6], [12, 15, 18], [28, 32, 36]]>>> [[M[row][col]*N[row][col] for row in range(3)] for col in range(3)][[2, 12, 28], [4, 15, 32], [6, 18, 36]]5:  讲字典中age键,按照条件赋新值

>>> bob  
{'pay': 3000, 'job': 'dev', 'age': 42, 'name': 'Bob Smith'}>>> sue  
{'pay': 4000, 'job': 'hdw', 'age': 45, 'name': 'Sue Jones'}>>> people = [bob, sue]>>> [rec['age']+100 if rec['age'] >= 45 else rec['age'] for rec in people]  # 注意for位置  [42, 145]  


列表推导式总共有两种形式:
①[x for x in data if condition]
    此处if主要起条件判断作用,data数据中只有满足if条件的才会被留下,最后统一生成为一个数据列表
​
②[exp1 if condition else exp2 for x in data]
    此处if...else主要起赋值作用,当data中的数据满足if条件时将其做exp1处理,否则按照exp2处理,最后统一生成为一个数据列表

例子如下:


data = ['driver', '2017-07-13', 1827.0, 2058.0, 978.0, 1636.0, 1863.0, 2537.0, 1061.0]
(1)若我要取得以上列表中值大于2000的数值,这里可以使用列表推导式的形式①:

[x for x in data if x > 2000]

得到如下结果(字符串类型数据被认为是无穷大数):

 ['driver', '2017-07-13', 2058.0, 2537.0]

(2)若要解决我上面提到的问题,则需要使用列表推导式的形式②

[int(x) if type(x) == float else x for x in data]

得到结果:

 ['driver', '2017-07-13', 1827, 2058, 978, 1636, 1863, 2537, 1061]


1、使用[]生成list

基本格式

variable = [out_exp_res for out_exp in input_list if out_exp == 2]
  out_exp_res:  列表生成元素表达式,可以是有返回值的函数。
  for out_exp in input_list:  迭代input_list将out_exp传入out_exp_res表达式中。
  if out_exp == 2:  根据条件过滤哪些值可以。


例一:


multiples = [i for i in range(30) if i % 3 is 0]print(multiples)# Output: [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]


例二:

def squared(x):
    return x*x
​
multiples = [squared(i) for i in range(30) if i % 3 is 0]print multiples
​
#  Output: [0, 9, 36, 81, 144, 225, 324, 441, 576, 729]

2、使用()生成generator

将俩表推导式的[]改成()即可得到生成器。

multiples = (i for i in range(30) if i % 3 is 0)print(type(multiples))#  Output: <type 'generator'>


二、字典推导式
​
字典推导和列表推导的使用方法是类似的,只不中括号该改成大括号。


{ key_expr: value_expr for value in collection if condition }

直接举例说明:


l = ["%02d:%02d" %(h,m) for h in range(0, 24) for m in range(0, 60, 5)]
​
d = {key:0 for key in s}print(d)print(sorted(d.key()))1:  用字典推导式以字符串以及其长度建字典


>>> strings = ['import','is','with','if','file','exception']  
  
>>> D = {key: val for val,key in enumerate(strings)}  
  
>>> D  
{'exception': 5, 'is': 1, 'file': 4, 'import': 0, 'with': 2, 'if': 3}  


例子一:大小写key合并

mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
​
mcase_frequency = {
    k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0)
    for k in mcase.keys()
    if k.lower() in ['a','b']
}print mcase_frequency
​
#  Output: {'a': 17, 'b': 34}


例子二:快速更换key和value

mcase = {'a': 10, 'b': 34}
​
mcase_frequency = {v: k for k, v in mcase.items()}print mcase_frequency
​
#  Output: {10: 'a', 34: 'b'}


三、集合推导式
它们跟列表推导式也是类似的。 唯一的区别在于它使用大括号{}{ expr for value in collection if condition }


例一:
squared = {x**2 for x in [1, 1, 2]}print(squared)# Output: set([1, 4])1:  用集合推导建字符串长度的集合


>>> strings = ['a','is','with','if','file','exception']>>> {len(s) for s in strings}    #有长度相同的会只留一个,这在实际上也非常有用 set([1, 2, 4, 9])  


嵌套列表是指列表中嵌套列表,比如说:

>>> L = [[1,2,3],[4,5,6],[7,8,9]]1: 一个由男人列表和女人列表组成的嵌套列表,取出姓名中带有两个以上字母e的姓名,组成列表

names = [['Tom','Billy','Jefferson','Andrew','Wesley','Steven','Joe']['Alice','Jill','Ana','Wendy','Jennifer',
'Sherry','Eva']]for循环实现:


tmp = []  
for lst in names:  
    for name in lst:  
        if name.count('e') >= 2:  
            tmp.append(name)  
  
print tmp  
#输出结果  
>>>   
['Jefferson', 'Wesley', 'Steven', 'Jennifer']  

用嵌套列表实现:

>>> [name for lst in names for name in lst if name.count('e')>=2]  #注意遍历顺序,这是实现的关键  
['Jefferson', 'Wesley', 'Steven', 'Jennifer']  

猜你喜欢

转载自blog.csdn.net/qq_21153997/article/details/95071695
今日推荐