自学Python第四天- python 的基础数据类型
python 的基础数据类型以是否可变可以分为 可变和不可变类型,以对象种类可以分为 数值类型、序列类型、集合类型、映射类型四类。
这里要强调一下变量和数据类型的关系。变量只是对某个对象的引用或是别名、指针、调用等等,其本身没有数据类型的概念。只有具体的对象才有数据类型的概念。
不可变类型
所谓不可变类型,指的是类型的值一旦有不同,那么它就是一个新的对象。给变量赋值不可变类型,其实就是新建一个对象,将变量指向该变量。
可变类型
可变类型是相对于不可变类型的,其对象内部的成员是可变化的,对象赋值给变量后,如果有变化,更改的可以是内部成员,而不是重新更改对象。
数值类型
数值类型是不可变类型,即每一个使用到的数值就是一个对象,占用一段特定的内存空间。数值型变量值的改变其实就是所引用的对象的改变,即所指向的内存地址的改变。
python 支持三种不同的数值类型:整形、浮点数和复数、布尔型。
整形 int
整数通常被称为整形,数值可以为正或负数,不带小数点。表示数字时,默认使用十进制(decimal)来表示。
有时候会使用八进制、十六进制、二进制来表示
进制 | 前缀 | 组成 | 示例 | 十进制转相应进制的方法 |
---|---|---|---|---|
十六进制 | 0x | 0-9,a-f | 0xff00 | hex() |
八进制 | 0o | 0-7 | 0o45 | oct() |
二进制 | 0b | 0-1 | ob11 | bin() |
一个整形对象长度为32bit,并且通常是连续分配内存空间的。例如 1 和 2 在内存中差32个 bit。
python 在初始化的时候会自动建立一个小整数对象池,这是一个从 -5到256的包含262个指向整数对象的指针数组。这些对象即使用户没有创建,python 后台也已经创建了。
>>> id(1)
2369251180784 # 数值对象 1 所在内存地址
>>> 80784 + 300 * 32
90384 # 如果每个数值对象占用 32 ,则对象 301 应该所在内存地址
>>> 80784 + 200 * 32
87184 # 如果每个数值对象占用 32 ,则对象 201 应该所在内存地址
>>> id(201)
2369251187184 # 数值对象 201 所在内存地址
>>> id(301)
2369251196048 # 数值对象 301 所在内存地址
浮点数 float
浮点数就是小数,对于很大或很小的浮点数,一般使用科学计数法表示。把10用e替代,例如 1.23*10^9就是1.23e9。
复数 complex
复数其实是一种特殊的浮点数,复数由实数部分和虚数部分构成,可以使用 a + bj 或者 complex(a,b) 表示,复数的 实数a 和 虚数b 都是浮点型。
数值的计算
除了加减乘除等基本运算,更多的科学计算需要使用导入 math 这个标准库,它包含了绝大多数我们可能使用到的科学计算函数。还有一些有用的内置函数,例如:
函数名 | 说明 |
---|---|
math.ceil() | 向上取整 |
math.floor() | 向下取整 |
math.pow() | 取幂次 |
abs() | 取绝对值 |
round() | 四舍六入五单双(四舍六入五成偶) |
布尔型 bool
布尔型只有2个值, True 和 False 。注意其首字母必须大写。在运算时,可以遵循非0非空即为真的原则。
序列类型
序列数据结构是一种可迭代的 (iterable) 数据结构,其拥有下标,即索引,默认从0开始。下标参数可以使用负数,即逆向移动指针。序列类型包含不可变的 str 、 tuple 、 bytes 和可变的 list 类型
字符串 str
python 使用单引号或双引号创建字符串,使用三引号创建文本字符串。普通字符串和文本字符串的区别是,文本字符串可以保留样式。比如换行,在字符串中使用 \n ,在文本字符串直接可以将回车作为换行。
字符串在内存中,是以每个字符存储一个字节的方式进行存储的。所以字符串其实是多个字符组成的序列。
在 python 中,可以将字符串看做一个字符数组来处理,即可以直接使用索引号获取字符成员,可以使用 in 等对于序列才能使用的方法。
字符串是不可变的数据类型。
在 python 中,可以使用 slice()
函数对字符串进行切片,其包含3个参数,分别是起始索引、结束索引+1、步长。也可以使用字符串的切片模式进行切片,参数同 slice()
函数,只是使用引号 “:” 分隔:
>>> name = 'summy brown'
>>> name[6:11] # 切片原则为左闭右开,所以参数2需要加1
'brown'
>>> name[6:] # 如果结束索引要到最后一项,则参数2可以省略
'brown'
>>> name[:5] # 从头开始则可以省略参数1
'summy'
>>> name[::2] # 步长意为每次取值时指针移动的次数
'smybon'
>>> name[::-1] # 步长为负值时,则类似于索引使用负数,逆向移动指针
'nworb ymmus'
拼接字符串
python 常用的拼接字符串有以下几种方法:
- 使用加号 “+” 连接字符串
使用加号连接字符串时需注意数据类型必须一致。另在 python 中,尽量少用 “+” 连接字符串。因为 String 对象是定长对象,一旦创建,长度就不可变化。使用 “+” 连接字符串,会开辟一段长度为总和长度的内存,而不是在一个对象存储空间中拼接。官方推荐的是使用字符串的 join 方法。 - 使用乘法 “*” 连接字符串
乘法连接类似于加法连接,都是使用字符串进行了一次运算,注意事项也和加法连接相同。不同的是 “*” 运算符后面需要使用 int 型
print('test-' * 3) # test-test-test-
- 使用逗号 “,” 连接字符串
可以使用逗号 " , " 将多个字符串连接为一个元组,再通过 join 方法将元组的各元素连接为一个字符串。如果直接逗号连接后 print ,则字符串之间会多一个空格间隔。如果使用
str1, str2 = 'hello', 'world'
str3 = str1, str2
print(str1, str2) # hello world
print(str3) # ('hello', 'world') ,即拼接为元组
print(''.join(str3)) # helloworld
- 直接连接字符串值
python 独有的方法,只要把两个字符串放一起,无论中间有空白或无空白,都会自动连接为一个字符串,此方法经常用于多行的字符串进行拼接,只是需要反斜杠 “\” 作为跨行连接。
print("Hello" "World") # HelloWorld
str_c = 'Love makes '\
'man grow up '\
'or sink down!'
print(str_c) # Love makes man grow up or sink down!
- 格式化方式拼接( % )
python 的字符串格式化拼接有点类似于 java 的 Es6 中的字符串拼接,不过 python 需要指定拼接变量的类型作为标记占位符:
%s 将一个字符串拼接
%d 将一个整形转换成字符串进行拼接,可以设置位数,前面补0或空格
%f 将一个浮点型转换成字符串进行拼接,可以设置小数点位数,后面补0
print('%s%s%s' % ('我', '是', '中国人')) # 我是中国人
age, name, score, num = 18, '小明', 98.5, 3
print('%s今年%d岁了' % (name, age)) # 小明今年18岁了
print('%s期中考试平均分为%.3f,是全年级第%03d名' % (name, score, num)) # 小明期中考试平均分为98.500,是全年级第003名
print('%s期中考试平均分为%.3f,是全年级第%3d名' % (name, score, num)) # 小明期中考试平均分为98.500,是全年级第 3名
- 使用
str.format()
方法拼接
str.format()
可以说是最通用(基本是万能的)的拼接方法了,不管后面拼接的数据是字符串还是数字,甚至元组、列表、字典、集合等数据类型,str.format()
统统都可以拼接到字符串中。
在要拼接的字符串中使用大括号{}来给拼接内容占位,后面按顺序依次传入对应的内容即可,也可以给每个占位的{}起一个变量名,然后通过关键字参数传递给str.format()
或直接使用已赋值的变量。
print("{}{}{}".format('我', '是', '中国人')) # 我是中国人
age, name, score, num = 18, '小明', 98.5, 3
print('python {}! format {}!'.format(666, 999)) # python 666! format 999!
# 小明今年18岁了,期中考试平均分为98.5,是全年级第3名
print(f'{name}今年{age}岁了,期中考试平均分为{score},是全年级第{num}名'.format())
# 生如夏花之绚烂,死如秋叶之静美! 需注意的是变量 a, b 在 print() 语句外无法使用
print('生如夏花之{a},死如秋叶之{b}!'.format(b='静美', a='绚烂'))
- 使用
str.join()
方法连接字符串
str.join()
是str.split()
方法的逆方法。这个方法接收一个列表,然后用字符串依次连接列表中的每一个元素。
str1, str2 = 'hello', 'world'
str3 = str1, str2
print(str3) # ('hello', 'world')
print(''.join(str3)) # helloworld
lists = ['hello', 'world']
print(lists) # ['hello', 'world']
print(''.join(lists)) # helloworld
- 使用字符串插值(F-strings)格式化字符串
在 python3.6 版本中,提出了一种新的字符串格式化机制,就是字符串插值。它提供了一种明确且方便的方式将 python 表达式嵌入到字符串中来进行格式化。而且 F-strings 运行速度很快,比 % 和str.format()
这两种格式化方法都快得多。更厉害的是,可以在 F-strings 中执行函数,只需将函数放在 {} 中。
score, num, name = 98.5, 3, '小明'
print(f'{name}期中考试平均得分{score},是全年级第{num}名!')
str_s = 'a k q j 10'
print(f'顺子! str_s.swapcase()') # 顺子! str_s.swapcase()
print(f'顺子! {str_s.swapcase()}') # 顺子! A K Q J 10
字符串常见操作
函数实例 | 说明 |
---|---|
str.find(sub) | 返回该元素最小的索引,如果没有则返回-1 |
str.index(sub) | 返回该元素最小的索引,如果没有则抛出错误 |
str.replace(old,new[,count]) | 将old字符替换为new字符,重复count次,无count则是全部替换 |
str.split(seq=None) | 以seq分割字符串,返回列表(数组)。默认值为None,以空格分割 |
str.startswith(prefix[,start[,end]]) | 判断字符串是否以前缀开始,返回bool值 |
str.endswith(suffix[,start[,end]]) | 判断字符串是否以尾缀结束,返回bool值 |
str.lower() | 字符串全部转为小写 |
str.upper() | 字符串全部转为大写 |
str.strip([chars]) | 去掉字符串左右的字符,默认为空格 |
str.isalpha() | 判断字符串是否全为字母,返回bool值 |
str.isdigit() | 判断字符串是否全为数字,返回bool值 |
str.isalnum() | 判断字符串是否全为数字或字母(不存在特殊字符),返回bool值 |
str.join(iterable) | 将指定序列中的元素以此字符串连接生成一个新的字符串 |
字符串的特殊操作
- 字符串中使用引号
由于 python 支持两种引号,所以如果要输出引号,不管是双引号还是单引号,只需将要输出的引号使用另一种引号包裹起来。或使用转义 \’ 这样的形式。
print('"') # 执行结果: "
print("''") # 执行结果: ''
print('\'') # 执行结果: '
- 转义字符串
需要使用特殊字符时可以使用转义字符 \ 反斜杠。列出一些常用的转义字符
转义字符 | 说明 |
---|---|
\(在行尾时) | 续行符 |
\|反斜杠符号 | |
\’ | 单引号 |
\" | 双引号 |
\b | 退格(Backspace) |
\n | 换行(光标移动到下一行) |
\r | 回车(光标移动到行首) |
\000 | 空 |
\v | 纵向制表符 |
\t | 横向制表符(tab 键) |
格式化字符串
拼接字符串的时候使用字符串插值十分方便,但是使用 % () 来格式化字符串也有其独有的作用:
符号 | 描述 |
---|---|
%s | 格式化字符串 |
%d | 格式化整数 |
%u | 格式化无符号整数(用处不大) |
%o | 格式化无符号8进制数 |
%x | 格式化无符号16进制数 |
%X | 格式化无符号16进制数(大写) |
%f | 格式化浮点数,可指定精度 |
%e | 用科学计数法格式化浮点数 |
%E | 同 %e |
%g | %f和%e的简写 |
%G | %F和%E的简写 |
字节类型 bytes
python3 将字节和字符串彻底分开了。区别在于字符串是以字符为单位进行处理,而 bytes 则是以字节为单位进行处理的。除此之外,操作和使用甚至内置方法上和字符串基本一样。
python3 中, bytes 通常用于网络数据传输、二进制图片和文件的保存等。
创建字节类型
字节型创建和字符串类似,只是在字符串值前增加小写 b 。
bytes_1 = b'hello' # 直接创建
bytes_1 = bytes('hello', encoding='utf8') # 返回值创建
字节型字符串转字符串
字节型的字符串可以直接转为字符串使用,只需要解码使用即可
b = b'hello'
type(b.decode())
列表型 list
列表型是 python 中最基本也是最常用的数据结构之一,它是一个有序可重复的 元素集合。从数据结构看,是一个可变长度的顺序存储结构,每一个位置存放的都是对象的指针。
创建列表
列表使用方括号包含所有元素,元素之间以逗号分隔。列表中保存的是指向个对象的指针,所以所包含元素的类型可以不一致。
list_1 = [1, 'ffff', True, 7.8]
创建列表除了赋值外,还可以使用返回值创建。使用 list() 方法转换类型时,只能用于序列类型的数据对象。
list_1 = list('hello world')
print(list_1) # ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
list_2 = list(123456) # 错误,因为整形不是序列类型
删除列表内的元素
可以使用 del()
、 list.remove()
或 list.pop()
删除列表内的元素。
list_1 = list('hello world')
del list_1[5] # 也可用 del(list_1[5])
print(list_1) # ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
list_1.remove('l')
print(list_1) # ['h', 'e', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
print(list_1.pop(4)) # w
print(list_1) # ['h', 'e', 'l', 'o', 'o', 'r', 'l', 'd']
del()
是删除目标元素(的指针)。
list.remove()
是删除第一个指定的值。
list.pop()
删除索引号所在元素并返回。默认最后一个元素。
列表的特殊操作
列表的 + 法就是将两个列表连接起来。
>>> list1, list2 = [1, 2, 3], [4, 5, 6]
>>> list1 + list2
[1, 2, 3, 4, 5, 6]
列表不能乘以列表,但是可以乘以整数,返回的是倍数的扩展
>>> list1 = [1, 2, 3]
>>> list1 * 4
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
列表可以像字符串一样进行切片
>>> list1=list("hello world")
>>> list1[::-1]
['d', 'l', 'r', 'o', 'w', ' ', 'o', 'l', 'l', 'e', 'h']
列表常用的内置函数
len()
返回列表的长度
max()
返回列表所有元素中值最大的一个
min()
返回列表所有元素中值最小的一个
list.reverse()
将列表自身逆序
list.sort()
将列表升序排序
list.slice()
将列表切片,同字符串的切片
list.append()
将参数对象作为元素添加至列表结尾
list.extend()
将序列对象的元素逐个添加至列表结尾
list.insert()
将参数对象插入到列表的参数索引处
list.count()
返回参数元素在列表中出现的次数
list.index()
返回参数元素在列表中第一次出现的索引
元组 tuple
元组也是序列结构,但是不可变序列。可以简单的理解为内容不可变的列表。除了在内部元素不可修改外,元组和列表的用法差不多。
元组所占用的内存比列表少,所以当存储的内容不需要改变时,推荐使用元组。
创建元组
与创建列表不同的是,创建元组不使用方括号 [] 而使用小括号 () 。
与列表相同的操作
元组的元素不可修改,但是可以进行访问的相关操作
- 使用索引访问元素
- 切片 (形成新元组对象)
tuple.count()
和tuple.index()
- python 内置函数:
reversed()
,sorted()
(反转和排序) - 加法及乘法
需要注意的是 reversed()
和 sorted()
方法,它们是 python 的内置函数。其中 reversed()
返回的是 revesed想型的对象,即需要强转使用。sorted()
即使参数为元组等类型,返回的是列表型。
元组的加法和乘法同列表,做拼接和扩展动作,返回新的对象。
集合类型
集合 set
集合 set 是一个无序不重复元素的集,主要用来进行关系测试和消除重复元素。是可变数据类型。集合数据类型的核心在于自动去重。
创建集合
集合使用大括号 {} 创建,并且元素以逗号分隔。当创建空集合时,使用 set()
来创建。集合内的元素是不重复的任意不可变元素,当集合内的元素是键值对时,集合就成了字典,所以说字典是特殊的集合。
使用集合
set.add(element)
添加
方法将参数作为元素添加至集合,如果重复则自动去重。需注意的是,其元素和字典的 key 一样,必须是不可变类型。哪怕是元祖,但是其中的元素包含了列表,也视为可变类型。set.update(object)
更新
方法将另一个对象更新到已有的集合中,这过程中会去重。更新的意义在于将对象拆开去重后添加到已有集合。set.remove(key)
删除指定元素
集合是无序的,是不能通过索引方式获取元素的,也不能通过 key 的方式获取元素。set.remove(key)
其实是将 key 值传入,通过元组不重复的特性找到了需要的元素。set.pop()
提取并删除(弹出)一个随机的元素(因为pop是根据索引操作,而集合是无序的)
映射类型
字典 dict
dict 型其实是一个键值对 (key : value) ,根据 key 的值计算 value 的地址。它具有非常快的查询和插入速度,是可变的数据类型。
字典的创建
字典使用大括号 {} ,每个元素都分为 key 和 value ,由 : 相隔,元素由 , 相隔。
dic = {'name': 'amy', 'age': 18}
字典也可以使用 dict(**kwargs)
即键值对形式创建
dic = dict(name = 'amy', age = 18)
字典还可以使用 dict(mapping)
即映射关系 (‘name’, ‘amy’) 来创建
dic = dict([('name', 'amy'), ('age', 18)])
字典的 key 是不可变数据类型(哪怕是元祖类型,但如果其中包含了列表也视为可变类型),value 可为任意类型。当创建时有重复键时则进行覆盖。
使用字典
字典和序列类型不同,是无序的有映射关系的对象的集合,所以字典没有索引下标的概念,更没有切片的说法。字典当中的元素是通过键来存取的,而不是通过偏移存取。
使用字典时,可以把相应的键取代索引写在方括号内,获取对应的值。
>>> dict_1 = {'name': 'amy', 'age': 18}
>>> dict_1['age']
18
注:如果索引的 key 不存在,则会报错。所以不确定时通常使用 dict.get(key)
方法获取值。
字典增加元素不向列表等,需要通过函数方法进行附加。可以使用直接赋值的形式增加字典的元素。
>>> dict_1 = {'name': 'amy', 'age': 18}
>>> dict_1['gender'] = 'female'
>>> dict_1
{'name': 'amy', 'age': 18, 'gender': 'female'}
修改元素类似增加元素,只是新增的同 key 元素会进行覆盖,就成了修改元素。
删除元素也是使用 del 加字典的 key 索引,也可以使用 dict.pop(key)
的形式提取相应元素的值并删除元素。
>>> dict_1 = {'name': 'amy', 'age': 18, 'gender': 'female'}
>>> del dict_1['gender']
>>> dict_1
{'name': 'amy', 'age': 18}
>>> dict_1.pop('name')
'amy'
>>> dict_1
{'age': 18}
字典常见的操作
字典常见的操作方法及函数有
dict.get(key[,default])
返回指定键的值,如果值不在字典中,则返回 default 值dict.items()
以列表返回可历遍的 (键,值)元组对dict.keys()
以列表返回字典所有的键dict.values()
以列表返回字典所有的值dict.fromkeys(iterable[,value])
返回一个字典,其 key 为 iterable 内的元素,value 默认值为 None(经测试和变量 dict 无关)
映射扩展:mapping
mapping 是一种表示一一对应的关系,例如 (‘name’, ‘amy’) ,即 name 和 amy 对应起来了。如果是多个一一对应的关系可以使用列表或元组来表示,如 [(‘name’, ‘amy’), (‘age’, 18)]。
映射扩展: map() 函数
map(func, *iterables)
将 iterables 可迭代的对象中的元素依次以 func 函数来进行处理,返回新的 map 型处理后的映射对象。
list_1 = list('123456')
list_1 = list(map(int, list_1))
print(list_1) # [1, 2, 3, 4, 5, 6]
映射扩展: zip() 函数
zip()
将参数中的可迭代对象按照一一对应的方式进行打包。
li_1, li_2 = ('name', 'age'), ('amy', 18)
print(dict(zip(li_1, li_2))) # {'name': 'amy', 'age': 18}