基本数据类型及内置方法
引子:序列
所谓序列,指的是一块可存放多个值的连续内存空间,这些值按一定顺序排列,可通过每个值所在位置的编号(称为索引)访问它们
在python中,序列类型包括字符串、列表、元组、集合和字典,这些序列支持以下几种通用的操作,但比较特殊的是,集合和字典不支持索引、切片、相加和相乘操作。
序列索引
序列中,每个元素都有属于自己的编号(索引)。从起始元素开始,索引值从 0 开始递增。
除此之外,Python 还支持索引值是负数,此类索引是从右向左计数,换句话说,从最后一个元素开始计数,从索引值 -1 开始
注意,在使用负值作为列序中各元素的索引值时,是从 -1 开始,而不是从 0 开始。
序列切片
切片操作是访问序列中元素的另一种方法,它可以访问一定范围内的元素,通过切片操作,可以生成一个新的序列。
序列实现切片操作的语法格式如下:
name[start : end : step]
name:表示序列的名称;
start:表示切片的开始索引位置(包括该位置),此参数也可以不指定,会默认为 0,也就是从序列的开头进行切片;
end:表示切片的结束索引位置(不包括该位置),如果不指定,则默认为序列的长度;
step:表示在切片过程中,隔几个存储位置(包含当前位置)取一次元素,也就是说,如果 step 的值大于 1,则在进行切片去序列元素时,会“跳跃式”的取元素。如果省略设置 step 的值,则最后一个冒号就可以省略
序列相加
Python 中,支持两种类型相同的序列使用“+”运算符做相加操作,它会将两个序列进行连接
这里所说的“类型相同”,指的是“+”运算符的两侧序列要么都是序列类型,要么都是元组类型,要么都是字符串。
序列相乘
Python 中,使用数字 n 乘以一个序列会生成新的序列,其内容为原来序列被重复 n 次的结果
In [20]: s = '测试'
In [21]: s * 2
Out[21]: '测试测试'
比较特殊的是,列表类型在进行乘法运算时,还可以实现初始化指定长度列表的功能
In [28]: [None] * 3
Out[28]: [None, None, None]
检查元素是否包含在序列中
Python 中,可以使用 in 关键字检查某元素是否为序列的成员,其语法格式为:
value in sequence
其中,value 表示要检查的元素,sequence 表示指定的序列。
和 in 关键字用法相同,但功能恰好相反的,还有 not in 关键字,它用法检查某个元素是否不包含在指定的序列中
和序列相关的内置函数
函数 | 功能 |
---|---|
len() | 计算序列的长度,即返回序列中包含多少个元素。 |
max() | 找出序列中的最大元素。注意,对序列使用 sum() 函数时,做加和操作的必须都是数字,不能是字符或字符串,否则该函数将抛出异常,因为解释器无法判定是要做连接操作(+ 运算符可以连接两个序列),还是做加和操作。 |
min() | 找出序列中的最小元素。 |
list() | 将序列转换为列表。 |
str() | 将序列转换为字符串。 |
sum() | 计算元素和。 |
sorted() | 对元素进行排序。默认升序。 |
reversed() | 反向序列中的元素。 |
enumerate() | 将序列组合为一个索引序列,多用在 for 循环中。 |
一 数字类型int与float
int整形
int整形专门用来表示整数,即没有小数部分的数。在 Python 中,整数包括正整数、0 和负整数。
和其他强类型语言不同,它们会提供多种整形类型,开发者要根据数值的大小,分别用不同的整形类型存储,以 C 语言为例,根据数值的大小,开发者要合理选择 short、int、long 整形类型存储,大大增加了开发难度。
Python 则不同,它的整型支持存储各种整数值,无论多大或者多小,Python 都能轻松处理(当所用数值超过计算机自身的计算功能时,Python 会自动转用高精度计算)。
float浮点数
浮点型数值用于保存带小数点的数值,Python 的浮点数有两种表示形式:
- 十进制形式:这种形式就是平常简单的浮点数,例如 5.12、512.0、0.512。浮点数必须包含一个小数点,否则会被当成整数类型处理。
- 科学计数形式:例如 5.12e2(即 5.12×102)、5.12E2(也是 5.12 ×102)。
使用:
数字类型主要就是用来做数学运算与比较运算,因此数字类型除了与运算符结合使用之外,并无需要掌握的内置方法
# 浮点数转化为百分数
avg_eng_count = 0.0343434
res = '%.2f%%'%(avg_eng_count*100)
二 字符串
简单地理解,字符串就是“一串字符”,也就是用引号包裹的任何数据,比如“Hello,Charlie”是一个字符串,“12345”也是一个字符串。
Python 3.x 中,字符串采用的是 Unicode 字符集
数据类型转换
数据类型转换:str()可以将任意数据类型转换成字符串类型
>>> type(str([1,2,3])) # list->str
<class 'str'>
>>> type(str({"name":"jason","age":18})) # dict->str
<class 'str'>
>>> type(str((1,2,3))) # tuple->str
<class 'str'>
>>> type(str({1,2,3,4})) # set->str
<class 'str'>
常用方法 | 描述 |
---|---|
s.endswith() s.startwith() |
判断是否以什么结束, 判断是否以什么开头 |
s.isdigit() |
判断是否全是数字 |
s.lower() s.upper() |
全部转化成小写,全部转化成大写 |
s.replace('a','1',2) | 替换2个'a'为'1',可以指定替换次数 |
strip, lstrip, rstrip | 移除左右两边的指定字符,只移除左边,只移除右边 |
format格式化输出 | s = '5{}7'😒.format(6) |
split,rsplit | split会按照从左到右的顺序对字符串进行切分,可以指定切割次数 |
join() | 从可迭代对象中取出多个字符串,然后按照指定的分隔符进行拼接,拼接的结果为字符串 |
index() | 找不到时会报错 |
s.count() |
统计元素的个数 |
s.find() |
查找元素索引位置默认返回第一个,如果没有该元素则直接返回-1 |
s.isalpha() |
判断是否全是字母 |
s.islower() s.isupper() |
判断是否全是小写 判断是否全是大写 |
center,ljust,rjust,zfill | 总宽度,字符串居中,两边字符;总宽度,字符串左对齐;总宽度,字符串左边全是0 |
expandtabs() | 修改\t制表符代表的空格数 |
captalize,swapcase,title | 首字母大写;大小写反转;没发单词的首字母大写 |
三 列表
从形式上看,列表会将所有元素都放在一对中括号 [] 中,相邻元素之间用逗号分隔
从内容上看,列表可以存储整数、实数、字符串、列表、元组等任何类型的数据,并且和数组不同的是,在同一个列表中元素的类型也可以不同
类型转换
但凡能被for循环遍历的数据类型都可以传给list()转换成列表类型,list()会跟for循环一样遍历出数据类型中包含的每一个元素然后放到列表中
>>> list('wdad') # 结果:['w', 'd', 'a', 'd']
>>> list([1,2,3]) # 结果:[1, 2, 3]
>>> list({"name":"jason","age":18}) #结果:['name', 'age']
>>> list((1,2,3)) # 结果:[1, 2, 3]
>>> list({1,2,3,4}) # 结果:[1, 2, 3, 4]
使用方法
方法 | 描述 |
---|---|
切片 | l.[0:1] 顾头不顾尾 |
len() | 长度 |
in not in | 成员运算 |
append() 添加 | 列表尾部追加元素 |
extend() | 一次性在列表尾部添加多个元素 |
insert() 插入 | 在指定位置插入元素 |
del(l[2]) 删除 | 删除索引为2的元素 |
pop() | 默认删除列表最后一个元素,并将删除的值返回, 括号内可以通过加索引值来指定删除元素 |
remove() | 括号内指名道姓表示要删除哪个元素,没有返回值 |
reverse() | 颠倒列表内元素顺序 |
sort() | 给列表内所有元素排序 默认降序 False; 字符之间的大小取决于它们在ASCII表中的先后顺序,越往后越大 |
四 元组
元组与列表类似,也是可以存多个任意类型的元素,不同之处在于元组的元素不能修改,即元组相当于不可变的列表,用于记录多个固定不允许修改的值,单纯用于取
定义方式
# 在()内用逗号分隔开多个任意类型的值
>>> countries = ("中国","美国","英国") # 本质:countries = tuple("中国","美国","英国")
# 强调:如果元组内只有一个值,则必须加一个逗号,否则()就只是包含的意思而非定义元组
>>> countries = ("中国",) # 本质:countries = tuple("中国")
类型转换
# 但凡能被for循环的遍历的数据类型都可以传给tuple()转换成元组类型
>>> tuple('wdad') # 结果:('w', 'd', 'a', 'd')
>>> tuple([1,2,3]) # 结果:(1, 2, 3)
>>> tuple({"name":"jason","age":18}) # 结果:('name', 'age')
>>> tuple((1,2,3)) # 结果:(1, 2, 3)
>>> tuple({1,2,3,4}) # 结果:(1, 2, 3, 4)
# tuple()会跟for循环一样遍历出数据类型中包含的每一个元素然后放到元组中
使用
元组只有两种方法
方法 | 描述 |
---|---|
tu.count() |
统计元素出现次数 |
tu.index |
查找元素索引 |
五 字典
和列表相同,字典也是许多数据的集合,属于可变序列类型。
不同之处在于,它是无序的可变序列,其保存的内容是以“键值对”的形式存放的。
字典中,习惯将各元素对应的索引称为键(key),各个键对应的元素称为值(value),键及其关联的值称为“键值对”
字典类型很像学生时代常用的新华字典。我们知道,通过新华字典中的音节表,可以快速找到想要查找的汉字。其中,字典里的音节表就相当于字典类型中的键,而键对应的汉字则相当于值。
定义方式
由于字典中每个元素都包含 2 部分,分别是键和值,因此在创建字典时,键和值之间使用冒号分隔,相邻元素之间使用逗号分隔,所有元素放在大括号 {} 中。
字典中的键必须唯一 | 字典中,不支持同一个键出现多次,否则,只会保留最后一个键值对。 |
---|---|
字典中的键必须不可变 | 字典中的值是不可变的,只能使用数字、字符串或者元组,不能使用列表。 |
遍历:默认遍历的是字典的key
方法 | 描述 |
---|---|
dic.keys() | 获取字典所有的key,返回一个迭代器,可以使用 list() 来转换为列表 |
dic.values() | 获取字典所有的value |
dic.items() | 获取字典所有的键值对 |
dic.get() | key存在,则获取key对应的value值,不存在,不会报错而是默认返回Nonekey, 不存在时,可以设置默认返回的值 |
dic.pop('name') | 通过指定字典的key来删除字典的键值对 |
dic.popitem() | 随机删除一组键值对,并将删除的键值放到元组内返回 |
dic.update() | 用新字典更新旧字典,有则修改,无则添加 |
dict.fromkeys(l,666) | 第一个参数序列l内的每个元素为键,值为第二个参数666 |
dic.setdefault() | 和get类似,key不存在则新增键值对添加到字典,并将新增的value返回 |
列表中的字典去重
s = [{'name': 'b'}, {'name': 'c'}, {'name': 'b'}]def DelRepeat(data,key): new_data = [] # 用于存储去重后的list values = [] # 用于存储当前已有的值 for d in data: if d[key] not in values: new_data.append(d) values.append(d[key]) return new_dataprint(DelRepeat(s, 'name'))
字典按照 key 排序 reverse=True 降序
for i in sorted(d) :
print ((i, d[i]), end =" ")
字典按照 value 排序
lambda 匿名函数
sorted(d.items(), key=lambda item:item[1])
使用operator的itemgetter进行排序
import operator
sorted(d.items(), key=operator.itemgetter(1))
将key和value分装成元组,再进行排序
f = zip(d.keys(), d.values())
c = sorted(f)
列表中字典排序
lis_dic = [{'name': 'hahha', 'age': 66}, {'name': 'rannie', 'age': 90}]
s = sorted(lis_dic, key = lambda i: (i['age'], i['name']))
# s = sorted(lis_dic, key=lambda i: i['name'], reverse=True)
import operator
all_comments = [{'publish_date': '6-21', 'age': 66}, {'publish_date': '6-22', 'age': 90}]
data= sorted(all_comments, key=operator.itemgetter('publish_date'), reverse=True)
六 集合
集合是一个无序的不重复的元素序列
集合、list、tuple、dict一样都可以存放多个值,但是集合主要用于:去重、关系运算
同一集合中,只能存储不可变的数据类型,包括整形、浮点型、字符串、元组,无法存储列表、字典、集合这些可变的数据类型,否则 Python 解释器会抛出 TypeError 错误
定义:在{}内用逗号分隔开多个元素,集合具备以下三个特点:
1:每个元素必须是不可变类型
2:集合内没有重复的元素
3:集合内元素无序
# 注意1:列表类型是索引对应值,字典是key对应值,均可以取得单个指定的值,而集合类型既没有索引也没有key与值对应,所以无法取得单个的值,而且对于集合来说,主要用于去重与关系元素,根本没有取出单个指定值这种需求。
方法 | 描述 |
---|---|
s.add() | add() 方法添加的元素,只能是数字、字符串、元组或者布尔类型 |
s.remove() | 删除指定元素,如果被删除元素本就不包含在集合中,则此方法会抛出 KeyError 错误 |
s.discard() | 同remove,区别是不会报错 |
集合去重复有局限性
# 1. 只能针对不可变类型
# 2. 集合本身是无序的,去重之后无法保留原来的顺序
关系运算
集合最常做的操作就是进行交集、并集、差集以及对称差集运算
图中有 2 个集合,分别为 set1={1,2,3} 和 set2={3,4,5},它们既有相同的元素,也有不同的元素。以这两个集合为例,分别做不同运算的结果。
运算操作 | Python运算符 | 含义 | 例子 |
---|---|---|---|
交集 | & union | 取两集合公共的元素 | >>> set1 & set2 |
并集 | | intersection | 取两集合全部的元素 | >>> set1 | set2 |
差集 | - difference | 取一个集合中另一集合没有的元素 | >>> set1 - set2 {1,2} >>> set2 - set1 |
对称差集 | ^ symmetric_difference | 取集合 A 和 B 中不属于 A&B 的元素 | >>> set1 ^ set2 |
七 可变类型与不可变类型
可变数据类型:值发生改变时,内存地址不变,即id不变,证明在改变原值
不可变类型:值发生改变时,内存地址也发生改变,即id也变,证明是没有在改变原值,是产生了新的值
拷贝就是拷贝,何来深浅之说?
Python中,对象的赋值,拷贝(深/浅拷贝)之间是有差异的,如果使用的时候不注意,就可能产生意外的结果
其实这个是由于共享内存导致的结果
拷贝:原则上就是把数据分离出来,复制其数据,并以后修改互不影响。
浅拷贝:数据半共享(复制其数据独立内存存放,但是只拷贝成功第一层)
l1 = [1,2,3,[11,22,33]]
l2 = l1.copy()
print(l2) #[1,2,3,[11,22,33]]
l2[3][2]='aaa'
print(l1) #[1, 2, 3, [11, 22, 'aaa']]
print(l2) #[1, 2, 3, [11, 22, 'aaa']]
l1[0]= 0
print(l1) #[0, 2, 3, [11, 22, 'aaa']]
print(l2) #[1, 2, 3, [11, 22, 'aaa']]
print(id(l1)==id(l2)) #Flase
复制对象最外层的内存。 最外层独立,第二次无法独立,会随l1变动
深拷贝:数据完全不共享(复制其数据完完全全放独立的一个内存,完全拷贝,数据不共享)
深拷贝就是完完全全复制了一份,且数据不会互相影响,因为内存不共享。
import copy
l2 = copy.deepcopy(l1)