Python之序列

        序列是一种数据存储方式,用来存储一系列的数据。在内存中,序列就是一块用来存放多个值的连续空间。比如一个整数序列:[10,20,30,40]。可以这样表示:

        由于Python3中一切皆对象,在内存中实际是按照如下方式储存的:

        a=[10,20,30,40]

        从图示中我们可以看出,序列中存储的是整数对象的地址,而不是整数对象的值。

        Python3常用的序列对象有:

        字符串、元组、列表、字典、集合

列表简介

        列表:用于存储任意数目、任意类型的数据集合。

        列表是内置可变序列,包含多个元素的有序连续的内存空间。

        列表的标准语法格式:a=[10,20,30,40]

        其中,10,20,30,40这些称为:列表a的元素。

        列表中的元素可以各不相同,可以是任意类型。比如:a=[10,'20','abc',True]

        列表对象常用方法如下:

方法要点描述
list.append(x)增加元素将元素x增加到列表list尾部
list.extend(alist)增加元素将列表alist所有元素加到列表list尾部
list.insert(index,x)增加元素将列表list指定位置index处插入元素
list.remove(x)删除元素将列表list中删除首次出现的指定元素x,若不存在该元素则抛出异常
list.pop([index])删除元素删除并返回列表list指定为止index处的元素,默认是最后一个元素
list.clear()删除所有元素删除列表list中所有元素,并不是删除该列表对象
list.index(x)访问元素返回第一个x在列表list的索引位置,若不存在x元素抛出异常
list.count(x)计数返回指定元素x在列表list中出现的次数
len(list)列表长度返回列表list中包含元素的个数
list.reserse()翻转列表所有元素原地翻转
list.sort()排序所有元素原地排序
list.copy()浅拷贝返回列表对象的浅拷贝

         Python的列表大小可变,根据需要随时增加或缩小。

        字符串和列表都是序列类型,一个字符串是一个字符序列,一个列表是任何元素的序列。在字符串中的很多方法,在列表中也有类似的用法,几乎一模一样。

列表的创建

基本[]创建

 list()创建

        使用list()可以将任何可迭代的数据类型装换为列表。

range()创建整数列表 

        range()可以帮助我们非常方便的创建整数列表,这个在开发中极具作用。语法格式为:

        range([start,] end [,step])

        start参数:可选,表示起始数字。默认是0

        end参数:必选,表示结尾数字(不包括该数字,左闭右开)

        step参数:可选,表示步长,默认为1

        Python3中range()返回的是一个range对象,而不是列表。我们需要通过list()方法将其转换成列表对象。

        

 推导式式生成列表

        使用推导式可以非常方便的创建列表,在开发中经常使用,需要涉及到for和if语句。

 列表元素的增加和删除

        当列表增加和删除元素是,列表会自动进行内存管理,大大减少了程序员的负担,但这个特点设计列表元素的大量移动,效率较低。除非必要我们一般只在列表的尾部添加元素或删除元素,这样会大大提高变成效率。

append()方法

        原地修改列表对象,真正在列表尾部添加新的元素,速度最快,推荐使用。

        此方法不创建新的对象!

+运算符操作 

        并不是真正的尾部添加元素,而是创建新的列表对象;将原列表的元素的新列表的元素依次复制到新的列表中。这样,会涉及大量的复制操作,对于操作大量元素不建议使用。

         通过如上测试,我们发现变量a的地址发生了变化。也就是创建了新的列表对象。

extend()方法

        将目标列表的所有元素添加到原列表的尾部,属于原地操作,不创建新的列表对象。

 insert()方法

        使用insert()方法可以将指定位置元素插入到列表对象的任意指定位置。这样会让插入位置后面所有的元素进行移动,会影响处理速度。设计大量元素移动是,尽量表面使用。

        list.insert(index,x)

        在列表list的index位置处插入元素x

        注:指定位置index既可以正向搜索,也可以反向搜索。

                index >= len(list),此时是在队尾插入;

                index < -len(list),此时是在队头插入。

        类似发生这种移动的函数还有remove()、pop()、del()。它们在删除非尾部元素时也会发生操作位置后面元素的移动。

乘法扩展

        使用乘法扩展列表,生成一个新列表,新列表元素为原列表的多次重复,返回该新列表。

         适用于乘法扩展的,还有字符串、元组等。

 列表元素的删除

del删除

       del list[index]

        删除原列表中指定位置的元素。

        注:index可以是正向搜索,也可以是反向搜索,但要求index合法,否者抛出异常。

 pop()方法

        pop()删除院原列表指定位置元素,如果未指定则默认操作列表最后一个元素,返回被删除的元素。指定位置同样既可以正向搜索,也可以反向搜索,要求合法,否者抛出异常。

remove()方法 

        删除首次出现的指定元素,若该元素不存在则抛出异常。

        remove()方法没有返回值!!!即返回的是None

 

列表元素访问和计数

通过索引直接访问元素

        我们可以直接通过索引直接访问元素。索引的区间长度在[0,列表长度-1]或[-列表长度,-1]这个范围。超过这个范围则会抛出异常。

index()获得指定元素在列表中首次出现的索引

        index()可以获得指定元素在列表中首次出现的索引。若指定元素不出现则抛出异常。

        语法是:index(value,[start,[end]])

        其中start和end指定了搜索的范围,遵循着左闭右开的原则,[start,end)。

        注:搜索范围同样可以正向搜索,也可以反向搜索。

count()获得指定元素在列表中出现的次数

        count()可以返回指定元素在列表中出现的次数。

成员资格判定

        判断列表中是否存在指定的元素,我们可以使用count()方法,返回0则表示不存在,返回大于0则表示存在。但是,一般我们会使用更简洁的in关键字来判断,直接返回True或False。

切片操作

        列表的切片操作和字符串类似。

        切片slice操作可以让我们快速提取子列表或修改。标准格式为:

        [起始偏移量start:终止偏移量end[:步长]]

        注:当步长省略时数遍你可以省略第二个冒号。左闭右开,也可以说是包头不包尾。

        典型操作(三个数为正数):

操作和说明示例结果
[:]        提取整个列表
[10,20,30][:]
[10, 20, 30]
[start:]从start索引开始直到结尾[10,20,30][1:][20,30]
[:end]从头开始直到end-1[10, 20, 30][:2][10, 20]
[start:end]从start开始直到end-1[10,20,30,40][1:3][20,30]
[start:end:step]从start提取到end-1,步长是step[10,20,30,40,50,60][1:6:2]

[20, 40, 60]

        其它操作(三个量为负数)的情况:

示例说明结果
[10,20,30,40,50,60,70][-3:]
倒数第三个[50, 60, 70]
[10,20,30,40,50,60,70][-5:-3]

倒数第五个到倒数第四个

(包头不包尾)

[30, 40]
[10,20,30,40,50,60,70][::-1]
步长为负,从右到左反向提取[70, 60, 50, 40, 30, 20, 10]

        切片操作时,起始偏移量和终止偏移量不在[0:字符串长度]这个范围,也不会报错。起始偏移量小于0则会被当作0,终止偏移量大于“长度”会被当成“长度”。例如:

 列表的遍历

        for obj in listObj:
                print(obj)

复制列表所有元素到新列表对象

        如下代码是否实现列表元素复制?

list1=[30,40,50]
list2=list1

         只是将list2也指向了list1指向的对象,也就是说list1和list2持有地址值是相同的,列表元素本身并没有复制。

        可以通过如下简单方式,实现列表元素内容的复制:

list1=[30,40,50,60]
list2=[]+list1

        还可以使用copy模块,使用浅复制或深复制实现复制操作。

列表排序

原列表排序

        使用sort()方法,修改原列表,不新建列表的排序。sort()方法无返回值。

 排序后生成新的列表

        通过使用内置函数sorted()进行排序,这个方法返回新列表,不对原列表进行修改。

        通过上面操作,可以看出生成的列表对象b和c都是完全新的列表对象。

reversed()返回迭代器

         内置函数reversed()也支持逆序排序吗,与列表对象reverse()方法不同的是,内置函数reversed()不对原列表做任何修改,只是返回一个逆序列表的迭代器对象。

 列表相关的其他内置函数汇总

max和min

用于返回列表中的最大值和最小值

 sum

        对数值型列表的所有元素进行求和操作,对非数值列表则会报错。

多维列表

二维列表

        一维列表可以帮助我们存储一维、线性的数据。

        二维列表可以帮助我们存储而二维、表格的数据。

        例如下表的数据:

姓名年龄薪资城市
高小一1830000北京
高小二1920000上海
高小三2010000深圳

        源码:

a=[
    ["高小一",18,30000,"北京"],
    ["高小二",19,20000,"上海"],
    ["高小一",20,10000,"深圳"]
  ]

        内存结构图:

元组tuple

        列表属于可变序列,可以任意修改列表中的元素。元组属于不可变序列,不能修改元组中的元素。因此,元组没有增加元素、修改元素、删除元素相关的方法。

        在元组中重点掌握元组的创建和删除,元组中元素的访问和计数即可。

        元组支持以下操作:

                1.索引访问

                2.切片操作

                3.连接操作

                4.成员关系操作

                5.比较运算操作

                6.计数:元组长度len()、最大值max()、最小值min()、求和sum()等。

元组的创建

        1.通过()创建元组。小括号可以省去。

                a=(10,20,30)  或者  a= 10,20,30

        如果元组只有一个元素,则必须后面加逗号。这时因为解释器会把(1)解释我整数1,(1,)解释为元组。

        2.通过tuple()创建元组

        tuple(可迭代的对象)

        例如:

  

         总结:

        tuple()可以接受列表、字符串、其他序列类型、迭代器等生成组。

        list()可以接受元组、字符串、其他序列类型、迭代器生成列表。

元组的元组访问和计数

        1.元组的元素不能修改

         2.元组的元素访问和列表一样,只不过返回的依然是元组对象。

         3.列表关于排序的方法list.sort()是修改原列表对象,元组没有该方法。如果要对元组排序,只能使用内置函数sorted(tupleObj),并生成新的列表对象

zip

        zip(列表1,列表2,……)将多个列表对应位置的元素组合成为元组,并返回这个zip对象。

 生成器推导式创建元组

        从形式上看,生成器推导和列表推导类似,只是生成器推导式使用小括号。列表推导式直接生成列表对象,生成器推导式生成的不是列表也不是元组,而是一个生成器对象

        我们可以通过生成器对象,转化成列表或者元组。也可以使用生成器对象_next_()方法进行遍历,或者直接作为迭代器对象来使用。不管什么方式使用,元素访问结束后,如果需要重新访问其中元素,必须重新创建生成器对象。

        生成器使用测试:

元组总结

        1.元组的核心是不可变序列。

        2.元组的访问和处理速度比列表快。

        3.与整数和字符串一样,元组可以作为字典的键,列表则永远不能作为字典的键使用。

字典dict

        字典是“键值对”的无序可变序列,字典中的每一元素都是一个“键值对”,包含:“键对象”和“值对象”。我们可以通过“键对象”实现快速获取、删除、更新对应的“值对象”。

        列表中我们通过“下标数字”找到对应的对象。字典中通过“键对象”找到对应的“值对象”。“键”是任意不可变数据类型,比如:整数、浮点数、字符串、元组。但是:列表、字典、集合这些可变对象,不能作为“键”。并且“键”不可重复。

        一个典型的字典的定义方式:

                a={'name':'phh','age':18,'job':'programmer'}

字典的创建

        1.我们可以通过{}、dict()来创建字典对象。

        2.通过zip()创建字典对象

         3.通过fromkeys创建值为空的字典

字典元素的访问

        为了测试各种访问方法,我们这里设定一个字典对象:

                a={'name':'phh','age':18,'job':'programmer'}

        1.通过 [键] 获得 “值”。若键不存在,则抛出异常。

        2.通过get()方法获得“值”。推荐使用。优点是:指定键不存在,返回None;也可以设定指定键不存在是默认返回的对象。推荐使用get()获取“值对象”。

         3.列出所有的键值对

        4.列出所有的键,列出所有的值。

         5.len() 键值的数目

 

         6.检测一个“键”是否在字典中。

字典元素添加、修改、删除

        1.给字典新增“键值对”。

        如果“键”已经存在,则覆盖旧的键值对;如果“键”不存在,则新增“键值对”。

 

         2.如果使用update()将字典中所有键值对全图添加到旧字典上。如果key值有重复,则直接覆盖。

        3.字典中元素的删除,可以使用del()方法;或者使用clear()删除所有键值对;pop()删除指定键值对,并返回对应的“值对象”。

         4.popitem()随机删除和返回该键值对。字典是“无序可变序列”,因此没有第一个元素、最后一个元素的概念;popitem弹出随机的项,因为字典并没有“最后的元素”或则其它有关顺序的概念。若想一个接一个地移除处理项,这个方法就非常有效(因为不用获取键的列表)。

序列解包

        序列解包可以用于元组、列表、字典。序列解可以让我们方便对多个变量赋值。

        序列解包用于字典时,默认是对'“键”进行操作;如果需要对键值进行操作,则需要使用items();如果需要对“值”进行操作,则需要使用values()。

 

 表格数据使用字典和列表存储,并实现访问

 

 

源代码:

r1 = {"name":"高小一","age":18,"salary":30000,"city":"北京"} 
r2 = {"name":"高小二","age":19,"salary":20000,"city":"上海"} 
r3 = {"name":"高小五","age":20,"salary":10000,"city":"深圳"} 

tb = [r1,r2,r3]     

#获得第二行的人的薪资 
print(tb[1].get("salary"))   
  
#打印表中所有的的薪资 
for i in range(len(tb)): # i -->0,1,2 
    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结构和大小一致,我们可以通过偏移量来读取指定

根据键查找“键值对”的底层过程

         明白一个键值对是如何存储到数组中,根据键对象取到值对象,理解起来就简单了。

 

         当我们a.get('name'),就是根据键‘name'查找到“键值对”,从而找到值对象'phh'。

        第一步,计算‘name’对象的散列值:

        和存储的底层流程算法一致,也是依次取散列值的不同位置的数字。 假设数组长度为 8,我们可以拿计算出的散列值的最右边 3 位数字作为偏移量,即“101”,十进制是数字 5。我们查看偏移量 5,对应的 bucket 是否为空。如果为空,则返回 None。如果不为空, 则将这个 bucket 的键对象计算对应散列值,和我们的散列值进行比较,如果相等。则将对 应“值对象”返回。如果不相等,则再依次取其他几位数字,重新计算偏移量。依次取完后, 仍然没有找到。则返回None。
        

        用法总结:

        1.键必须可散列

                (1) 数字、字符串、元组,都是可散列的。

                (2) 自定义对象需要支持下面三点:

                        支持hash()函数

                        支持通过__eq__()方法检测相等性。

                        若a==b为真,则hash(a)==hash(b)为真。

        2.字典在内存中开销巨大,典型的空间换时间。

        3.键查询速度很快。

        4.往字典添加新键可能导致扩容,导致散列中键的次序变化。因此,不要在遍历字典的同时进行字典的修改。

集合set

        集合是无序可变,元素不能重复。实际上,集合底层是字典实现,集合所有元素都是字典中的“键对象”,因此是不能重复且唯一的。

集合的创建和删除

        1.使用{}创建对象,并使用add()方法添加元素。

        在使用add()方法时,添加已经存在集合中元素不会抛出异常。

        2.使用set(),将列表、元组等可迭代对象转为集合。如果原数据存在重复数据,则值保留一个。

        3.remove()删除指定元素;clear()清空整个集合。

 

 集合相关操作

        像数学中概念一样,Python对集合也提供了并集、交集、差集等运算。

 

 

 

 

  • 5
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值