python集合类型应用场景_Python学习笔记四:集合、字典和运算符

一、集合

在 Python 中,集合由内置的 set 类型定义。

集合的特性:无序,元素唯一 ,可变。属于散列类型。

1. 创建和使用集合

要创建集合,需要将所有项(元素)放在花括号({})内,以逗号(,)分隔。

>>> se = {1,2,'a','b'} #{1, 2, 'b', 'a'}

>>> se3 = set() #用工厂方法定义空集合

>>> se4 = {} #

2. 特点

(1) 无序性

集合里的元素具有无序性。

>>> se = {1,'s',55,5} # {'s', 1, 5, 55}

(2) 唯一性

元素唯一,会去掉重复元素

>>> se={1,1,1,1,3} # {1, 3}

>>> se3={1,2,[3,3,4]} ##TypeError: unhashable type: 'list' list不可哈希

#列表是可变的,所以不能满足唯一性

Hash()哈希函数可以检验对象是不是可哈希的

>>> hash((1,2,3)) #元组可以哈希 3713081631934410656 返回的是哈希位置

>>> hash([1,2]) # TypeError: unhashable type: 'list'

(3) 可变

3. 集合的运算

se={1, 2, 3,4}

se2={3, 4, 5, 6}

(1) 属于(元素与集合), 返回bool值

>>> 3 in se2 #True

>>> se in se2 #False

not in #不属于

(2) 包含于(集合与集合), 返回bool值

>>> se < se2 #False

>>> se <= se2 #False

(3) 交集:&

两个集合共有的元素,即重复的部分,返回一个集合

>>> se & se2 #{3,4}

(4) 并集:|

取两个集合所有的元素,返回一个集合

>>> se | se2 #{1, 2, 3, 4, 5, 6}

(5) 差集:-

前面的集合减去与后面的集合重复的元素,返回一个集合

>>> se - se2 #{1, 2}

(6) 与非集:^

取两个集合各自独有的元素,返回一个集合

>>> se ^ se2 #{1, 2, 5, 6}

4. 集合的方法

>>> dir(set)

['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']

(1) set.add(…)

添加单个元素到集合里。随机地添加到任意位置。如果添加一个已存在的元素,这将没有影响。无返回值。

>>> se.add(5) #{1,2,3,4,5}

(2) set.update(…)

添加多个元素。要放入可迭代的对象。无返回值。

>>> se.update('123') #{1,2,3,4,'1','2','3'}

>>> se.update([1,2,3]) #添加已存在的元素,会自动去重

>>> se.update(1,2,3) # TypeError: 'int' object is not iterable

(3)set.remove(…)

指定移除一个集合里存在的元素,如果元素不在集合里,会抛出KeyError。无返回值。

>>> se.remove(1) #{2, 3, 4, '3', '2', '1'}

>>> se.remove('1') #{2, 3, 4, '3', '2'}

>>> se.remove(7) #KeyError: 7

(4)set.clear()

移除集合里所有的元素。无返回值。

>>> se.clear() #{}

二、字典

这里介绍一种可通过名称来访问其各个值的数据结构。这种数据结构称为映射(mapping)。字典是Python中唯一的内置映射类型,其中的值不按顺序排列,而是存储在键下。键可能是数、字符串或元组。

字典是另一种可变容器模型,可存储任意类型的对象。

字典的特性 : key 唯一, 无序 , 可变。属于散列类型。

1. 字典的用途

字典(日常生活中的字典和Python字典)旨在让你能够够轻松地找到特定的单词(键),以获悉其定义(值)。

在很多情况下,使用字典都比使用列表更合适。下面是Python字典的一些用途:

表示棋盘的状态,其中每个键都是由坐标组成的元组

存储文件修改时间,其中的键为文件名

数字电话/地址簿

假如有如下的名单:

>>> names = ['Alice', 'Beth', 'Cecil', 'Dee-Dee', 'Earl']

如果创建一个小型数据库,在其中存储这些人的电话号码,该如何办呢?一种方法是再创建一个列表。假设只存储四位的分机号,这个列表将类似于:

>>> numbers = ['2341', '9102', '3158', '0142', '5551']

创建这些列表后,就可像下面这样查找Cecil的电话好吗:

>>> numbers[names.index('Cecil')] #'3158'

这可行,但不太实用。实际上,你希望能干过像下面这样做:

>>> phonebool['Cecil'] #'3158'

如何达成这个目标呢?只要phonebook是个字典就行了。

2. 创建和使用字典

字典以类似于下面的方式表示:

Phonebook = {'Alice':'2341', 'Beth'':'9102','Cecil':'3258'}

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

注意:在字典(以及其他映射类型)中,键必须是独一无二的,如果同一个键被赋值两次,后面的值会被记住,而字典中的值无需如此。值可以取任何数据类型,键必须是不可变的,如字符串、数字或元组。

>>> di={'a':111,'b':222,'c':333}

>>> di={} #class 'dict'

3. 函数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'}

>>> di2=dict(a=111) #{'a': 111}

#di2 = (2_a=111) #报错

#di2 = (_a=111) #报错

键要符合变量的命名规则

>>> di['c']=3 #{'c': 3} 修改

4. 基本的字典操作

字典的基本行为在很多方面都类似于序列。

len(d)返回字典d包含的项(键值对)数。

d[k]返回与键k相关联的值。

d[k] = v将值v关联到键k。

del d[k]删除键为k的项。del d删除整个字典。

k in d检查字典d是否包含键为k的项。

虽然字典和列表有多个相同之处,但也有一些重要的不同之处。

键的类型:字典中的键可以是整数,但并非必须是整数。字典中的键可以是任何不可变的类型,如浮点数(实数)、字符串或元组。

自动添加:即便是字典中原本没有的键,也可以给它赋值,这将在字典中创建一个新项。然而,如果不使用append或其他类似的方法,就不能给列表中没有的元素赋值。

成员资格:表达式k in d(其中d是一个字典)查找的是键而不是值,而表达式v in l(其中l是一个列表)查找的是值而不是索引。这看似不太一致,但你习惯后就会觉得相当自然。毕竟如果字典包含指定的键,检查相应的值就很容易。

提示:相比于检查列表是否包含指定的值,检查字典是否包含指定的键的效率更高。数据结构越大,效率差距就越大。

5. 将字符串格式设置功能用于字典

在第3章介绍过,可使用字符串格式设置功能来设置值的格式,这些值是作为命名或非命名参数提供给方法format的。在有些情况下,通过在字典中存储一些列命名的值,可让格式设置更容易些。

例如,可在字典中包含各种信息,这样只需在格式字符串中提取所需的信息即可。为此,必须使用format_map来指出你讲通过一个映射来提供所需的信息。

>>> phonebook #{'Beth': '9102', 'Alice': '2341', 'Cecil': '3258'}

>>> "Cecil's phone number is {Cecil}.".format_map(phonebook)

#"Cecil's phone number is 3258.

像这样使用字典时,可指定任意数量的转换说明符,条件是所有的字段名都是包含在字典中的键。

6.字典方法

>>> dir(dict)

['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

(1) dict.clear()

d.clear() -> 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) dict.copy(…)

d.copy() -> a shallow copy of D

方法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']}

>>> y['machines'][0]='aaa' #原值一起变化

>>> x #{'username': 'henry', 'machines': ['aaa', 'baz']}

>>> y #{'username': 'mlh', 'machines': ['aaa', 'baz']}

如你所见,当替换副本中的值时,原件不受影响。然而,如果修改副本中的值(就地修改而不是替换),原件也将发生变化,因为原件指向的也是被修改的值。

为避免上述问题可以使用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) dict.fromkeys(…)

fromkeys(iterable, value=None, /) method of builtins.type instance

Returns a new dict with keys from iterable and values equal to value.

方法fromkeys创建一个新字典,其中包含指定的键,且每个键对应的值都是None。返回一个新字典。

>>> {}.fromkeys(['name', 'age']) #{'age': None, 'name': None}

这个示例首先创建了一个空字典,再对其调用方法fromkeys来创建另一个字典,这显得有点多余。你可以不这样做,而是直接对dict(前面说过, dict是所有字典所属的类型)调用方法fromkeys。

>>> dict.fromkeys(['name', 'age']) #{'age': None, 'name': None}

如果你不想使用默认值None,可提供特定的值。这里只能批量生成,所以只能放一个值。

>>> dict.fromkeys(['name', 'age'], '(unknown)')

#{'age': '(unknown)', 'name': '(unknown)'}

(4) dict.get(…)

d.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.

方法get查询键在不在字典里面,如果键k在,返回键k的值,不存在则返回None或者可以自定义返回值。

>>> di = {'a':111, 'b':222, 'c':3, 'd':444}

>>> di.get('c') #3

>>> di.get('e')

你可指定“默认值”,这样将返回你指定的值而不是None。

>>> di.get('e','wobuzai') #'wibuzai'

>>> di.get('c','wobuzai') #3

通常,如果你试图访问字典中没有的项,将引发错误。而使用get在访问字典中不存在的项时默认返回None,并且不会引发上述错误。

>>> d = {}

>>> print(d['name'])

Traceback (most recent call last):

File "", line 1, in ?

KeyError: 'name'

而使用get不会这样:

>>> print(d.get('name')) #None

如果字典包含指定的键, get的作用将与普通字典查找相同。

>>> d['name'] = 'Eric'

>>> d.get('name') #'Eric'

(5) dict.items()

d.items() -> a set-like object providing a view on D's items

方法items返回一个包含所有字典项的列表迭代器,其中每个元素都为(key, value)的元组形式。字典项在列表中的排列顺序不确定。

>>> di.items()

#dict_items([('a', 111), ('b', 222), ('c', 3), ('d', 444)])

然而,如果你要将字典项复制到列表中,可自己动手做。

>>> list(di.items())

#[('a', 111), ('b', 222), ('c', 3), ('d', 444)]

返回值属于一种名为字典视图的特殊类型,字典视图可用于迭代。另外,你还可确定其长度以及对其执行成员资格检查。

>>> it = di.items()

>>> len(it) #4

>>> ('a', 111) in it #True

视图的一个优点是不复制,它们始终是底层字典的反映。当底层字典的内容被修改时,视图呈现出来的是修改后的值。

>>> di['a'] = 99

>>> ('a', 111) in it #False

>>> di['a'] = 0

>>> ('a', 0) in it #True

(6) dict.keys()

d.keys() -> a set-like object providing a view on D's keys

方法keys返回一个字典视图,其中包含指定字典中的键。

>>> di.keys()

#dict_keys(['a', 'b', 'c', 'd'])

(7) dict.values()

d.values() -> an object providing a view on D's values

方法values返回一个字典视图,其中包含指定字典中的值。不同于方法keys,方法values返回的视图可能包含重复的值。

>>> di.values()

#dict_values([99, 222, 3, 444])

(8) dict.pop()

d.pop(k[,d]) -> v

方法pop可用于获取与指定键相关联的值,并将该键-值对从字典中删除。

>>> di.pop('c') #3

>>> di # {'a': 99, 'b': 222, 'd': 444}

>>> di.pop() #会不会像list,pop()一样删除最后一个项呢?

Traceback (most recent call last):

File "", line 1, in

di.pop()

TypeError: pop expected at least 1 arguments, got 0

(9) dict.popitem()

d.popitem() -> (k, v)

方法popitem类似于list.pop,但list.pop弹出列表中的最后一个元素,而popitem随机地弹出一个字典项,因为字典项的顺序是不确定的,没有“最后一个元素”的概念。如果你要以高效地方式逐个删除并处理所有字典项,这可能很有用,因为这样无需先获取键列表。返回字典中被删除的一项。

>>> di.popitem() #('d', 444)

如果字典为空字典,则会抛出KeyError

>>> di2={}

>>> di2.popitem()

Traceback (most recent call last):

File "", line 1, in

di2.popitem()

KeyError: 'popitem(): dictionary is empty'

(10) dict.setdefault(…)

d.setdefault(k[,d]) -> d.get(k,d), also set D[k]=d if k not in D

方法setdefault有点像get,因为它也获取与指定键相关联的值,但除此之外,setdefault还在字典不包含指定的键时,在字典中添加指定的键-值对。

>>> di = {'a': 99, 'b': 222}

>>> di.setdefault('a') #99

>>> di.setdefault('e')

>>> di #{'a': 99, 'b': 222, 'e': None}

>>> di.setdefault('e')

>>> di.setdefault('d',444) #{'a': 111, 'b': 222, 'c': None, 'd': 444}

类似get,但是能改变字典。

>>> di.setdefault('a',666) #111

如你所见,指定的键不存在时,setdefault返回指定的值并相应地更新字典。如果指定的键存在,就返回其值,并保持字典不变。与get一样,值是可选的;如果没有指定,默认为None。

(11) dict.update()

d.update([E, ]**F) -> None. Update d from dict/iterable E and F.

If E is present and has a .keys() method, then does: for k in E: d[k] = E[k]

If E is present and lacks a .keys() method, then does: for k, v in E: d[k] = v

In either case, this is followed by: for k in F: d[k] = F[k]

方法update使用一个字典中的项来更新另一个字典。

>>> di = {'a': 99, 'b': 222, 'e': None}

>>> x = {'a':123,'f':555}

>>> di.update(x)

>>> di #{'a': 123, 'b': 222, 'e': None, 'f': 555}

对于通过参数提供的字典,将其项添加到当前字典中。如果当前字典包含键相同的项,就替换它。

可像调用本章前面讨论的函数dict(类型构造函数)那样调用方法update。这意味着调用update时,可向它提供一个映射、一个由键值对组成的序列(或其他可迭代对象)或关键字参数。

7. 字典和列表的区别

dict的特点:

查找和插入的速度极快,不会随着key的增加而变慢。

需要占用大量内存,内存浪费多。

List的特点是:

查找和插入时间随着元素的增加而增加。

占用空间小,浪费内存很少。

所以,dict是使用空间换取时间。

8. 可变,不可变

可变,不可变:就在id不变的情况下,增值,改值

id() # 每个对象有唯一的 id

如何区分一个对象,是否 可变

hash() # 成一个 唯一的哈希值。

如果不能被hash,就说明这对象是可变的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值