本系列为自己学习Python的笔记,如有误,欢迎大家指正
元祖tuple
列表属于可变序列,可以任意自古列表中的元素,元素属于不可变序列,不能修改元祖中的元素,因此,元祖没有增加元素、修改元素、删除元素等相关的方法。
元祖支持如下操作:
- 索引访问
- 切片操作
- 连接操作
- 成员关系操作
- 比较运算操作
- 计数:元祖长度len() 最大值max() 最小值min() 求和sum()
元祖的创建
-
通过()创建元祖,小括号可以省略
a = (10,20,30) 或者 a = 10,20,30
如果元祖只有一个元素,则必须后面加逗号,这是因为解释器会把(1)解释为整数1 (1,)解释为元祖。
a = (1,) type(a)
-
通过tuple()创建
tuple(可迭代的对象)
a = tuple() b = tuple("a,b,c") c = tuple([2,3,4]) d = tuple(range(3))
总结:tuple()可以接收列表、字符串、其他序列类型、迭代器生成元祖。
list()可以接收元祖、字符串、其他序列类型、迭代器等生成列表
元祖的元素访问和计数
-
元祖的元素不能修改
a = (10,20,30,40) a[3] = 15 #报错 TypeError
-
元祖的元素访问和列表一样,只不过返回的仍然是元祖对象
a = (10,20,30) a[1] a[0:2]
-
列表关于排序的方法list.sorted()是修改原列表对象,元祖没有该方法,如果要对元祖排序,只能使用内置函数sorted(tupleObj),并生成新的列表对象
zip
zip(列表1,列表2…)将多个列表对应的位置的元素组合成为元祖,并返回这个zip对象。
a = [10,20,30]
b = [40,50,60]
c = [70,80,90]
d = zip(a,b,c)
list(d)#[(10,40,70),(20,50,80),(30,60,90)]
生成器推导式创建元祖
从形式上看,生成器推导式与列表推导式类似,只是生成器推导式使用小括号,列表推导式直接生成列表对象,生成器推导式生成的不是列表也不是元祖,而是一个生成器对象。
我们可以通过生成器对象,转换成列表或者元祖,也可以使用生成器对象的__next__()
方法进行遍历,或者直接作为迭代器对象来使用。不管什么方法,元素访问结束后,如果需要重新访问其中的元素,必须重新创建该元素的生成器对象。
s = (x*2 for x in range(5))#迭代器对象
s
tuple(s)
list(s) #此时为空 因为只能访问一次
s = (x*2 for x in range(5))
s.__next__() #访问下一个元素
元祖总结
- 元祖的核心是不可变序列
- 元祖的访问和处理速度比列表块
- 与整数和字符串一样,元祖可以作为字典的键,列表则永远不能作为字典的键使用
字典
字典是键值对的无序可变序列,字典中的每个元素都是一个“键值对”,包含:“键对象”和“值对象”.可以通过键对象实现快速获取、删除、更新对应值对象。
列表中我们通过下标数字找到对应的对象,字典中通过键对象来找对应的值对象。键是任意的不可变对象,比如:整数 浮点数 字符串 元祖 ;但是列表、字典、激活这些可变对象,不能作为“键”,并且“键”不可重复。
值可以是任意的数据,并且可重复。
字典的创建
-
我们可以通过{} dict()来创建字典对象
a = { 'name':'slp','age':18,'job':'teacher'} b = dict(name='slp',age=18,job='teacher') a = dict([("name","18"),("age",18)]) c = { } #空字典对象 d = dict() #空字典对象
-
通过zip()创建字典对象
k = ['name','age','job'] v = ['slp',18,'teacher'] d = dict(zip(k,v))
-
通过fromkeys创建值为空的字典
a = dict.fromkeys(['name','age','job'])
字典元素的访问
-
通过键获得值,若键不存在,则抛出异常
a = { 'name':'slp','age':18} a['name'] #slp a['job'] #KeyError
-
通过get()方法获得值,推荐使用,有点是:指定键不存在,返回None,也可以设定指定键不存在时默认返回的对象
a = { 'name':'slp','age':18} a.get('name')
-
列出多有的键值对
a.items()
-
列出所有的键,列出所有的值
a.keys() a.values()
-
len()键值对的个数
-
检测一个键是否在字典中
'name' in a
字典元素添加、修改、删除
-
给字典新增“键值对”。如果“键”已经存在,则覆盖旧的值,如果不存在,则新增键值对
a = { 'name','slp'} a['address']='sx'
-
使用update()将新字典中所有键值对全部添加到旧字典上,如果key重复,则直接覆盖
a = { 'name':'slp','age':18} b = { 'name':'hp','address':'sx'} a.update(b)
-
字典中元素的删除,可以使用del()方法,或者clear()删除所有键值对;pop()删除指定键值对,并返回对应的“值对象”
a={ 'name':'slp', 'age':18} del(a['name'])
-
popitem():随机删除和返回该键值对,字典是无序可变序列,因此没有第一个元素,最后一个元素的概念,popitem()弹出随机的项,因为字典并没有最后的元素或其他顺序概念,若想一个一个删除,则这个非常有效
a = { 'name':'slp','age':18} a.popitem()
序列解包
序列解包是可以用于元祖、列表、字典。序列解包可以让我们方便的对多个变量赋值、
x,y,z = (20,30,10)
x #20
(a,b,c)=(9,8,10)
a #9
[a,b,c]=[10,20,30]
c #30
序列解包用于字典时,默认是对键进行操作;如果需要对键值进行操作,则需要使用items(),如果需要对值进行操作,则需要使用values()
s = {
'name':'slp','age':18}
name,age = s
name #'name'
name,age=s.items()
name#{'name','slp'}
例子
表格数据使用字典和列表存储,并实现访问
姓名 | 年龄 | 薪资 | 城市 |
---|---|---|---|
高小一 | 18 | 30000 | 北京 |
高小二 | 19 | 20000 | 上海 |
高小五 | 20 | 10000 | 深圳 |
# -*- coding: utf-8 -*-
"""
Created on Fri Jan 15 14:06:22 2021
@author: sangliping
"""
r1 = {
'name':'高小一','age':18,'salary':30000,'city':'北京'}
r2 = {
'name':'高小二','age':19,'salary':10000,'city':'上海'}
r3 = {
'name':'高小五','age':20,'salary':10000,'city':'深圳'}
tb = [r1,r2,r3]
print(tb)
# 获得第二行人的薪资
print(tb[1].get('salary'))
#打印表中所有的薪资
for i in range(len(tb)):
print(tb[i].get('salary'))
# 打印表的所有数据
for i in range(len(tb)):
print(tb[i].get('name'),tb[i].get('age'),tb[i].get('salary'),tb[i].get('city'))
字典核心底层原理
字典对象的核心是散列表,散列表是一个稀疏矩阵,数组的每个单元叫做bucket,每个bucket有两部分:一个是键对象的引用,一个是值对象的引用
由于所有bucket结构和大小一致,我们可以通过偏移量来读取指定bucket
将一个键值对放进字典的底层过程
a = {
}
a['name']='slp'
假设字典a对象创建完成后,数组长度为8:
我们要把’name’='slp’这个键值对放到字典对象a中,首先第一步需要计算键的散列值,python中可以通过hash()来计算 bin(hash('name'))
由于数组长度为8,我们可以拿计算出的散列值的最右边3位数字作为偏移量,即101,十进制是5,我们查看偏移量5对应的bucket是否为空,如果为空,则将键值对放进去,如果不为空则依次取右边3位作为偏移量,也就是100,查看偏移量为4的bucket是否为空,直到找到为空的bucket将键值对放进去。
根据键查找“键值对”的底层过程
当我们调用a.get(‘name’)的时候,就是根据name查找到键值对,从而找到该对象。第一步仍然是计算散列值。
和存储的底层流程算法一致,也是依次取散列值的不同位置的数字。假设数组长度为8我们可以拿计算出的散列值的最右边3位数字作为偏移量,查看对应10进制位置的bucket是否为空如果为空返回None,如果不为空,则进行比较,如果相等,则作为值返回,如果不相等,则依次取其他几位进行比较。如果最后依然没有找到,则返回None.
总结:
- 键必须可散列
- 数字 字符串 元祖都是可散列的
- 自定义对象需要支持下面三点
- 支持hash()函数
- 支持
__eq__()
方法检测相等性 - 若
a==b
为真,则hash(a)==hash(b)
也为真
- 字典在内存中开销巨大,典型的空间换时间
- 键查询速度很快
- 往字典里面添加新键可能导致扩容,导致散列表中键的次序变化,因此,不用在遍历字典的同时进行字典的修改
集合
集合是无序可变,元素不能重复,实际上,集合底层是字典实现,集合的所有元素都是字典中的键对象,因此是不能重复且唯一的
集合创建和删除
-
使用{}创建集合对象,并使用add()方法添加元素
a = { 3,5,7} a.add(9)
-
使用set(),将列表、元组等可迭代对象转换成几个。如果眼里数据存在重复值,则只保留一个。
a = ['a','b'] b = set(a)
-
remove()删除指定元素,clear()清空整个集合
集合相关操作
像数学中概念一样,python对集合也提供了并集、交集、差集等运算
a = {
1,2}
b={
's','l'}
a|b #并集
a&b #交集
a-b #差集
a.union(b) #并集
a.intersection(b) #交集
a.difference(b) #差集
微信搜一搜【梓莘】或扫描下方二维码交个朋友共同进步。文章持续更新中。目前在整理python百战学习笔记,期待后续更多的更新哦。