Python3内置数据结构学习1-数值型&列表&元组

python

Python3内置数据结构

    本篇是对Python3内置数据结构的初步学习与小结,用于复习巩固使用,如有理解偏差的地方,还望各位大佬指正。


Python3数据类型

    Python3的数据类型主要为一下六种类类型:

数值型:

int、float、complex、bool

序列对象:

列表 list
元组 tuple
字符串 str

键值对:

集合set
字典dict

    按照数据是否可变还可以分为:

可变数据类型:

列表、字典、集合

不可变数据类型:

数值型、字符串、元组

    Python是个动态的、强类型语言:赋值即定义,也就是说Python中不需要变量提前声明自己的类型,而是在赋值的那一刻才创建变量。实际上Python中变量本身没有类型,我们得到的类型指的是该变量指向的内存空间中实际数据的类型。

动态语言:指的数据类型的是否强制指定

优点:不需要提前指定变量数据类型,便于数据类型转换。动态语言的魅力在于让开发人员更好的关注需要解决的问题本身,而不是冗杂的语言规范。

缺点:不能在编译时检查数据类型,只会在运行的时候报错,而这个错误有可能会在项目上线后才出现,这时在再调试可能为时已晚。Python3.5后加入了类型注解以缓解这个问题,但根本问题仍然难以解决。

强类型语言:用print(‘a’+1)分别强弱,报错就是强类型,可以正常打印就是弱类型。JS就是典型的弱类型,Python则是强类型。弱类型的隐式转换,容易在看不到的地方出现问题。

print('a' + 1) 

    JS:
    JS是弱类型

    Python:
    python


数值型

    Python的数值型支持:int float complex bool

int:在Python是长整型数值,与C语言不同的地方在于,Python3把整型int和长整型long,合并成一个,且这个新的int没有大小限制,可以无限增大直到内存空间撑满。

float:浮点型,与C语言相似,由整数部分和小数部分组成,除了正常十进制,也支持科学计数法表示。

complex:复数型,由实数和虚数部分组成,两个部分用‘+’连接,复数部分用‘j’结尾,实数和虚数都可以缺省,其中实数和虚数部分都是浮点数,同样也支持科学计数法,例如3.14+3.33j,4.23e-3j。

bool:布尔型,只有两个实例,True和False,实际上bool型就是特殊的int,相当于1和0,可以直接参与整数运算。

    类型转换:Python内建多种类型转换,在Python一切皆对象的特性下,这些类型实际上都是类class,只是当成函数来使用,必须加括号。

int():返回int类型,是纯粹的取整,忽略浮点数,不会进位。

float():返回浮点数。
complex(x, y):返回复数。
bool:返回布尔值,除了与False等价的类型返回False,其余值全部返回True。


数值运算

    数值运算的运算符:Python的运算符与C基本相似。Python3开始区分自然除法"/”,和取整除法“//”。另外Python选择“**”作为乘方符。

>>>2 + 1  # 加法
3
>>> 3.4 - 2 # 减法
1.3
>>> 3 * 5  # 乘法
15
>>> 2 / 4  # 自然除法,得到一个浮点数
0.5
>>> 1 // 2 # 整除除法,得到一个整数
0
>>> 14 % 3 # 取余 
2
>>> 2 ** 3 # 乘方
8

注意:
    在混合运算时,Python会把整型转换成为浮点数,与C,Java的风格相似,保留此处的隐式类型转换更符合真实计算需求。
    混合运算


数值处理函数

    很多方法的参数只接受int型,运算后返回的数据可能还需要类型转换和数值处理。我们之前说的到的int()方法可以取整,返回整型,但是会忽略浮点数,那么如果我们需要判断是否进位该怎么做?Python同样提供了多种方法以满足使用。

round()函数:

round()函数取整遵循四舍六入,五去取偶数,偶数取最近偶数。
    round()函数取整

调用Python的数学模块math:

math.floor()地板取整,可以向下取整。
math.ceil()天花板取整,可以向上取整。
    取整
整除 // 默认是向下取整 也就是 math.floor
    在这里插入图片描述

    除了取整上下限问题,还有其他常用的数值处理方法。

max(), min() 返回最值

可以直接比较多个数字大小,也可以放入一个可迭代对象。
    取极值
注意该方法反复使用的效率问题,可能比不上if 语句。

进制函数:返回对应进制数的字符串

bin():二进制,以0b开头
oct():八进制,以0o开头
hex():十六进制,以0x开头
    进制转换



线性结构—列表list

    Python列表是线性结构,是由C语言的数组改写而来,比如加入了元数据包括列表长度、最大最小值等,因此我们可以通过len()函数轻易从列表元数据获得列表长度,时间复杂度为O(1),获得效率提升。

list 内的个体称作元素,由若干元素组成列表。
list 使用 [ ] 表示。
list 元素可以是任意对象(数字、字符串、对象、列表等)。
list 是线性有序的数据结构。
list 在内存中是一片连续空间,线性编址。
list 列表内元素有顺序,每个元素都有顺序索引。
list 寻址可以直接按照内存地址移位寻址,一步到位。
list 是可变的,可以修改数据 。

    列表是Python 中使用最频繁的可变数据类型,可以完成大多数集合类的数据结构实现。序列都可以进行的操作包括索引,切片,加,乘,检查元素(成员)。


列表的构建

    创建一个列表类型:常见方式

list1 = [ ] 		 # 直接使用空的[ ],生成一个空列表

list2 = [1,2,3,‘str’,[232]] 	 #直接定义一个列表

list3 = list()  	 # 使用list()方法,生成一个空列表。

list4 = list(iterable)   #使用一个可迭代对象生成列表

需要注意:
    列表里面什么都可以放进去对象,类型,亦或是另一个列表,都无所谓,因此,创建列表的时候,必须清楚,里面放的是不是自己想要的元素。
列表不能在生成是指定大小,后期追加元素需谨慎。


列表的索引

    索引也称为下标,与其他序列数据类型一样,列表也可以通过索引完成一系列操作。

正向索引: 从左至右,从0开始,0,1,2,3,4…n-1,为列表中每一个元素编号
负向索引: 从右至左,从-1开始, -1,-2,-3,-4…-n。
正负索引不可以超界,否则直接抛出异常IndexError
    列表索引

    列表通过索引访问:
    list[index]

index就是索引,使用中括号访问,这种直接索引效率很高为O(1)。

    列表查询:
    index(value,[start,[stop]]):匹配索引

通过值value,从指定区间查找列表内的元素是否匹配
匹配第一个就立即返回索引,从右向左
匹配不到,抛出异常ValueError

    列表计数:
    count(value)匹配重复次数

遍历列表,时间复杂度为O(n)
返回列表中匹配value的次数

    效率问题在这里同样值得注意,上面两种方法都是通过遍历查询的,其时间复杂度为O(n),尽量减少此类遍历操作,可以优化算法,提升效率。


列表元素修改

    索引访问修改:
    直接点对点,就地修改,高效实用。

list[index] = value
索引不能超界,否则会报错

    列表插入元素:
    insert(index, object) -> None

在指定的索引index处插入元素object
返回None就意味着没有新的列表产生,就地修改
时间复杂度是O(n),尽量少用

    insert()方法,索引可以超过上下界。

超越上界,尾部追加 -> append()
超越下界,头部追加

    列表在内存中的特性就是线性编址,如果进行insert()插入操作,那就相当于在排列紧密的队伍中差异入一个人,那么后面的人就必须都后退一位。列表的内存空间也是这样,插入索引位及之后的元素,全部都要后移,这样势必引占用性能及内存,引起效率问题,时间复杂度是O(n)。因此,列表的插入insert()能少用就少用。
insert()方法超越上界就得到了append()方法,该方法直接在列表的队尾插入元素,不需要移动列表内其他元素,时间复杂度是O(1),这是列表修改所推荐使用的方法,也是常用方法。

    队尾插入元素:
    append(object) -> None

列表尾部追加元素,返回None
返回None就意味着没有新的列表产生,就地修改
时间复杂度是O(1),推荐使用

    列表追加方法:
    extend(iteratable) -> None :队尾追加可迭代对象

将可迭代对象的元素追加进来
返回None,就地修改
就地修改

需要注意:
    列表生成的时候就有预留的内存空间,少量追加没有影响,但是大面积追加,就可能导致垃圾回收GC机制启动,重新规整内存空间,导致突发高占用问题,甚至无法操作。

    列表连接:
    + -> list

连接操作,将两个列表连接起来
返回一个新的列表,原列表不变
本质上调用的是__add__()方法

    列表重复:
    * -> list

重复操作,将本列表元素重复n次,返回新的列表

    在进行列表重复操作的时候,我们可以发现这么一个问题,列表中内嵌列表的元素并没有被实际复制进来。
可以看出该列表内的元素相当于引用类型,其实存的是数据对应的内存地址,而不是真正的数据,直接修改真实数据,所有引用类型都变了,其实我们可以看做是指针变量。
    列表重复操作

    Python中没有常量,我们可以把数字等字面常量可以当成普通类型,认为数字存的就是自己,但其实所有数据都是存的地址,不过字面常量存在大量引用,地址稳固,不会被丢弃。
通过这一点我们不难理解为什么Python的变量不能以数字开头,如果允许1 = x,那么字面常量1被赋值成x,那么真正的数据1,就没有引用对象了,被丢弃掉,程序必然崩溃。

    列表删除操作:
    remove(value) -> None

从左至右查找第一个匹配value的值,移除该元素。
返回None,就地修改
需要移动索引后的列表元素,时间复杂度为O(n),不推荐使用

    列表弹出:
    pop([index]) -> item

不指定索引index,就从列表尾部弹出一个元素
指定索引index,就从索引处弹出一个元素,索引超界抛出IndexError错误

    如果pop()指定索引,则需要移动索引后的列表元素,时间复杂度为O(n)。但是如果不指定索引,只弹出最后一个元素的,而这种用法时间复杂度仅为O(1),我们推荐使用的方法。

    pop弹出

    列表清空:
    clear() -> None

清除列表所有元素,剩下一个空列表。
删除该list元素的实例,其元素引用计数-1,真正内存删除交给GC机制。
语句执行看着的快,但是GC机制择机仍是要进行的。
    列表清空

    列表翻转:
    reverse() -> None

将列表元素反转。
返回None,就地修改
不推荐使用这该方法,时间复杂度为O(n),通常我们只要倒序索引就可以实现列表翻转。
列表翻转

    列表排序:
    sort(key=None, reverse=False) -> None

对列表元素进行排序,默认升序,
返回None,就地修改
reverse改为True,则按降序排列
    降序排列
key可以指定一个函数,sort按照指定的key方法排序

lst.sort(key=function)
指定key可以按不同类型比较:sort(key = str) 高阶函数 全部按照str比较大小。原本强类型语言Python不能混合比较,但是指定了key就可以做到了,但是我们不建议进行不同类型比较。
    指定key排序

该方法内置多种排序算法适应多种数量级排序,但也尽量少用,时间复杂度为O(nlogn)。

    列表in查询:
    item in list -> bool

判断元素是否在列表中,返回一个布尔值。
与index查询索引方法相似,不同的是,查询失败不会报错,只返回一个False,而很多时候我们只是想要一个判断,不需要得到元素索引,这个时候使用in方法比较好。
时间复杂度为O(n),尽量少用。
    in查询


列表复制

    列表复制:
    copy() -> List

返回一个新的列表
    copy1
通过上面的实例,我们明显可以发现,这种copy方法如果不改变嵌套列表的数据,只改变列表的浅层元素,copy()得到的列表与是相同且分离的两个列表。但是我们改变嵌套列表的数据,这就出现了问题。
    copy2
很明显copy得到了新列表,并没有真正的独立于原列表,新列表中存放的数据与原列表完全相同,这也导致原列表中的内层引用也保留了下来,而不是相对应的保存了真实数据。
这个时候我们引入两种拷贝概念:影子拷贝,深拷贝

    影子拷贝:
    shadow copy

影子拷贝,也叫浅拷贝,遇到引用类型,只是复制了一个引用而已。上面的copy()方法就是典型的浅拷贝,不能冻结复制时列表中指向的索引真实数据。

    深拷贝:
    deepcopy

通过deepcopy()进行深层次的递归拷贝,我们可以得到一个冻结了复制时刻,原列表中所有真实数据,包括引用类型所指向的数据。

copy模块提供了deepcopy
    深拷贝


线性结构—元组tuple

    元组tuple与列表十分相似,同样是一个由有序的元素组成的集合序列,核心不同点在于元组类型一旦生成,其内的元素本身不可修改。不过和浅拷贝类似,虽然元组本身的元素不可修改,但是其中的引用对象仍然可以使用原有的增删改操作,使元组最终引用的数据产生变化。

tuple内的个体称作元素,由若干元素组成列表
tuple使用( )表示。
元素可以是任意对象(数字、字符串、对象、列表等)。
tuple在内存中是一片连续空间,线性编址。
tuple列表内元素有顺序,每个元素都有顺序索引。
tuple寻址可以直接按照内存地址移位寻址,一步到位。
tuple不可变,是只读的,没有增删改。
存在tuple中的实际内容不可变,但是其引用的内容允许变化.
初始化空tuple(),但是如果加参数必须加上都会 “,” (1,) 不然就是个优先级运算(1+3)

    以下就是元组类型的典型增删改错误操作,运行后会直接报错。

    元组操作报错


元组的定义

    tuple() -> empty tuple

直接返回一个空元组
    空元组

    tuple(iterable) -> tuple

用可迭代对象生成,一个新的元组对象
    元组初始化

    tuple直接赋值:

通过把一个元组直接赋值给变量名,得到一个元组对象
    元组赋值


元组操作

    元组的索引操作,查询操作与列表的一致,不再赘述,区别在于元组的不可变特性,因而元组没有增、删、改的操作方法。

需要注意:
    元组之间可以进行‘ + ’或‘ * ’这样的运算符操作,但是这并不意味着元组可以增加元素,而是重新生成了一个新的元组对象,这一点和字符串的‘+’运算操作很相似。

元组的‘ + ’运算符操作
元组+操作

    元组删除:
    元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组,如下实例:

del tup
    元组删除


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值