Python 3 第二章 数据类型
任何一个程序,都离不开数据。甚至可以把程序理解为,算法+数据结构。
算法就是我们程序的逻辑控制,数据结构是如何组织数据。
计算机底层表示数据,无非是一个一个的比特位,使用二进制数据表示,
这是因为在电子元器件中,二进制的0和1可以方便的表示低电平和高电平两种状态。
可是0和1对于我们人来说,识别这些数据是什么,就有点太晦涩了。
所以高级语言会把这些数据封装,定义,分成了大至上几种基本的数据类型。
比如数字类型,包括整数,小数。
字符串类型,包括各种编码的,比如中文 ,英文
布尔类型,包括真,假两种状态
下面我们就详细的说说每一种数据类型的特性和用法
1. 整数 int
1.1 二进制 八进制 十六进制
整数其实是数字类型中使用最为广泛的类型
十进制整数就是一个一个的自然数,0,1,2... 也包括负数,-1,-2,-3...
另外整数不仅仅是方便人阅读的十进制数,由于计算机底部是用二进制表示的
所以python中保留了二进制的整数类型, 以0b开头,需要注意的是二进制就必须用0和1两个数字来表示
就如同十进制只能用0~9十个数字来表示一样
比如
>>> 0b123 File "<stdin>", line 1 0b123 ^ SyntaxError: invalid syntax >>> 0b1010101 85 >>>
但是有一个问题,二进制数表示一个数字时,不太方便书写,因为他太长了
比如,用二进制数来表示256, 需要用0b1010101这么长来书写,如果数字更大,这个长度就会更长
比如65535, 需要用16位个1来表示,0b1111111111111111',而且只用01两个数字,很容易写错
为了能高效的表示二进制数,又能快速的和二进制数字进行转换,人们又发明了八进制和十六进制
八进制使用0~7八个数字来表示,在python中八进制以0o 开头,
如65535使用八进制来表示
>>> 0o177777
65535
十六进制使用0~9 十个阿拉伯数字来表示还不够,所以又加上了 A,B,C,D,E,F 六个字母凑成16个,来表示
如65535使用十六进制来表示就只需要4个f
>>> 0xffff 65535
实际上程序设计中使用最广的就是十进制和十六进制,十进制是给人读的,十六进制常用来代替冗长的二进制
1.2 进制转换
数字本身只是代表一个值,这个值是超越进制的,这个值可以用十进制表示,也可以用二进制,八进制,十六进制表示
所以进制之间是可以转换的。
这个地方可能有点难,需要一些数学知识,请大家做好准备,不过不要怕,只会用到加法和乘法。
我们先来研究十进制,首先十进制数只能用0~9十个数字来表示,如何做到只用0~9十个数字来表示呢
就是每一位数字都用0~9十个数字来表示,每一位表示的值,应该是这一位的数字*位权重值
比如个129,这个十进制数字,个位的权重值应该是1,个位数字是9,那个位表示的值应该是 1*9
十位的权重值是10, 数字是2,所以十位数字表示的值是 10 * 2
百位的权重值是100, 数字是1, 所以百位数字表示的值是100 * 1
所以129的值 应该是 1*9 + 10*2 + 100 * 1 = 129
百 十 个
1 2 9
位的权重值是怎么来的?最右边的位的权重值永远是1,因为一位数字的时候 ,无论是二进制,八进制,十六进制还是十进制的表示的都是数字本身
比如一位数字1 ,无论在什么进制中,都是1,因为一位数字他们的权重值都是相等的, 1*1 =1
>>> 0o1==0x1==0b1==1
True
那往左边一位的权重值怎么算呢,因为几进制我们就要用几个数字来表示一位,等到不够用了才会进一位
比如十进制129,个位再加1的时候,进一位到十位,个位清零。进一位,那左边一位的权重值应该是 进制数 * 1
同样的道理, 十位如果 再进一位到百位的话,百位的权重值应该是 进制数*进制数 * 1
下面我们来看二进制 1101, 按照十进制权值来算,算出来的13就是二进制1101的值

八进制和 十六进制的算法也是一样的 ,值得一提的是十六进制、八进制可以快速的和二进制转换
因为一个十六进制, 可以由4 个二进制位来表示 ,因为4 个二制位表示的范围是0~15,刚好是一个十六进制位的表示范围
同样一个八进制位,可以由3个二进制位来表示,因为 3个二进位表示的范围是0~7,刚好是一个八进制位的表示 范围
这就是为什么我们有了一个二进制还要再设计十六进制和八进制的原因。
用十六进制和八进制表示 ,可以缩短书写长度,还可以和二进制互相转换。
以上讲的是我们自己算,在python里已经给我们提供了进制的互相转换
首先如果是整数类型,无论是二进制,十进制,八进制还是十六进制,我们都 不需要去转换,
因为Python解释器在翻译的时候,底层都 会统一成二进制,他们的值是一样的
我们甚至可以让他们直接计算
>>> 0b10 + 0o4+ 0xf + 12 33
转换只发生在我们需要表示的时候,也就是和字符串之间的转换
整数转换成对应进制的字符串
>>> hex(20) '0x14' >>> oct(20) '0o24' >>> bin(20) '0b10100'
>>> hex(0o17) '0xf' >>> oct(0x22) '0o42' >>> bin(0xf) '0b1111'
进制字符串转整数
>>> int('123') 123 >>> int('1011',2) 11 >>> int('0xff', 16) 255 >>> int('0o45', 8) 37
练习 输入十进制和想要转换的进制数,打印出对应的进制数
例如输入 18 16
输出0x12
2. 字符串 str
字符串是一种非常重要的数据类型,如果的计算机程序已经不只是用来运算科学问题了
大部分的程序是用来模拟现实事物的。目前计算的应用,用来科学运算是占20%,另外80%都是用来事物处理。
模拟事物,用的最多的类型就是字符串,字符串可以表示一段文本,一段数据,一段程序,几乎是我们看到的任何东西,就算是数字很多情况也是用字符串来表示的
所以学好字符串,以及怎么去操作字符串,非常重要。
我们已经知道python中,用引号包起来的就是字符串,可以是单引号',又引号", 三个单引号''',三个双引号"""
字符串其实是一种数据类型,这种数据类型在python中用str来表示
每个实际的字符串都是这种数据类型的一个对象
这有点类似于 人 这种定义是一个类型, 张三,一个具体的人,是人这种类型的对象
python是很彻底的面向对象的语言,所以,python中所有的都是对象 ,包括数据,整数,字符串,以及后面学的其它类型
作为一个对象,就像人一样,可能会有各种各样的行为,比如人可以吃饭,可以说话,可以工作
字符串作为对象,也一样会有很多行为,下面我们一起看一下,字符串可以有哪些行为和方法
2.1 大小写变换
| 方法名 | 方法功能 |
| capitalize | 字符串首字母变成大写 |
| lower | 字符串全部变成小写字母 |
| casefold |
字符串全部转小写字母 包含其它非英文字母的转换 比如德语,法语 |
| upper | 字符串全部转大写 |
| swapcawe |
字符串中大小写翻转, 大写变小写,小写变大写 |
| title | 所有的单词首字母大写 |
test = 'abcdefDEFIEIJFI' print(test.capitalize()) print(test.lower()) print(test.upper()) print(test.swapcase()) title_s = 'hello world' print(title_s.title())
练习 美元转人民币,让用户连续输入,直到用户输入q,或Q,打印出bye 并退出程序
while True: meiyuan = input('请输入多少美元>>>') if meiyuan.lower() == 'q': print('bye') break meiyuan = int(meiyuan) print(meiyuan/6)
2.2 判断方法
| 方法名 | 方法功能 |
| islower | 判断字符串是否全部为小写 |
| isupper | 判断字符串是否全部为大写 |
| isalpha | 判断字符串是否全部为文字(字母或汉字) |
| isalnum | 判断字符串是否只有数字和文字(字母或汉字) |
| isdecimal | 判断字符串是否只有十进制数字,阿拉伯数字 |
| isdigit |
判断字符串是否只有数字字符, 包含其它语言的数字字符 |
| isnumeric |
判断字符串是否只有数字类型,包含中文,一二三 |
| istitle | 判断字符串是否是标题类型 |
| isspace | 判断字符串是否全是空白字符 |
| isprintable | 判断字符串是否存在可打印字符 |
| startswith | 判断字符串是否以指定字符串开头 |
| endswith | 判断字符串是否以指定字符串结尾 |
| isidentifier | 判断字符串是否是标识符(符合变量命名规则) |
test = 'abc' print(test.islower()) print(test.isupper()) test = 'abcex你好123' print(test.isalpha()) print(test.isalnum()) '''1234567890 ①②③④⑤⑥⑦⑧⑨ 一二三四五六七八九十''' num = '一二三四五六七八九十' print(num.isdecimal()) print(num.isdigit()) print(num.isnumeric()) test = 'acd_8d8,' print(test.isidentifier()) title_s = 'Hell, world' print(title_s.istitle()) test = ' ' print(test.isspace()) test = 'dajgo"ie\n\n\nabcd' print(test) test = '\t\n\a\b' print(test.isprintable()) test = '0xff' print(test.startswith('0o')) print(test.endswith('ff'))
2.3 排版方法
| 方法名 | 方法功能 |
| center | 在字符串两边填充指定字符 |
| ljust | 在字符串左边填充指定字符 |
| rjust | 在字符串右边填充指定字符 |
| zfill | 在字符串右边充0 |
| extandtabs | 制表扩充 |
2.4 格式化
名字和位置占位替换 format 名字和位置点位替换进阶 format_map s = 'hello, {name}' print(s) print(s.format(name='jack')) print(s.format_map({'name':'jack'})) s = 'hello, {0},{1}..' print(s.format('jack', 'tom')) s = 'hello, %sabcd %s' % ('蜡台\n\t', 'jack') print(s) s = 'hello, %rabcd %s' % ('蜡台\n\t','tom') print(s)
2.5 查找和统计
查找子串的位置 index 查找子串的位置进阶 find 统计子串出出现的次数count s = 'abcdefgabcdef' print(s.index('cd', 9, 11)) print(s.find('cd', 9, 10)) # print()print(s.count('cd', 9))
2.6 替换和去除
去除指定字符串strip 去除左边 lstrip 去除右边 rstrip 对照替换 maketrans, translate 指定替换 replace s = ' \n abcd \t ' print(s.strip()) s = 'adbcdba' print(s.strip('adba')) print(s.lstrip('a')) print(s.rstrip('a')) m = ''.maketrans('abc', '123') print(s.translate(m)) print(s.replace('a', '1233'))
2.7 分割和拼接
按指定字符三分 partition 从右边开始三分 rpartition 指定字符分割 split 从右边指定字符分割 rsplit 按行分割 splilines 拼接字符串 join s = 'abcdef123456\nfdieoifjao' print(s.partition('f')) print(s.rpartition('f')) print(s.split('f', 1)) print(s.rsplit('f', 1)) print(s.splitlines(True)) s = 'abcdef' print(','.join(s)) print('_'.join(s).split('_')) print('123,456'.split(','))
2.8 编码 解码
# 编码 s = '中国' # unicode print(s.encode('utf-8')) #utf-8 汉字三个字节 print(s.encode('gbk')) # 两个字节 print(s.encode('gb2312')) s='Ascii code' print(s.encode('ascii')) s = "你是最胖的boy" s = s.encode('utf-8') print(s) print(s.decode('utf-8')) # 解码和编码的格式不同,报错 # print(s.decode('gbk'))
2.9 最常用的
join 拼接
split 分割
find 查询
lower 小写转换
upper 大写转换
strip 去掉两边空白字符
replace 指定替换
encode 编码
decode 解码
格式化
2.10 通用方法
# 切片 s = '近观山有色,细听水无声' print(s[0]) print(s[-1]) print(s[1:5]) print(s[:]) print(s[::2]) print(s[::-1]) # 获取长度 print(len(s)) # 迭代 # for 变量 in 字符串: # 循环语句 # else: # 正常结束循环执行 # 支持break continue s = '相见时难别亦难' for i in s: print(i) else: print('结束迭代')
3. 列表 list
列表是一组有顺序的元素集合,用[] 括起来,元素之间用逗号分割
列表中的元素可以是任意的数据类型
[1, 2, 3.5, '列表', True, [1, [2, 3]]]
列表支持的方法
在列表末尾增加元素 append
在列表末尾扩展 extend
在列表中间插入 insert(index, value) 把value插入到index位置 之前
按索引删除一个元素 pop
按值删除一个元素 remove
清空列表 clear
翻转列表 reverse
排序 sort
浅拷贝 copy
列表统计元素 count
列表查找 index
# 列表方法 l = [] print(l) l.append('西瓜') print('append: ', l) l.extend(['苹果', '黄瓜', '西瓜']) print('extend: ', l) l.insert(1, '葡萄') print('insert: ', l) index = l.index('葡萄') print('index(葡萄): ', index) count = l.count('西瓜') print('count(西瓜): ', count) remove = l.remove('西瓜') print('remove(西瓜):', l) l.reverse() print('reverse: ', l) popitem = l.pop() print('pop: ', l, 'popitem', popitem) popitem = l.pop(0) print('pop: ', l, 'popitem', popitem) l.clear() print('clear: ', l) l = [17, 92, 79, 11, 26, 60, 3, 52, 20, 59] l.sort() print('sort: ', l) l.sort(reverse=True) print('sort(reverse):', l) #重要:append, pop,remove ,index
[] append: ['西瓜'] extend: ['西瓜', '苹果', '黄瓜', '西瓜'] insert: ['西瓜', '葡萄', '苹果', '黄瓜', '西瓜'] index(葡萄): 1 count(西瓜): 2 remove(西瓜): ['葡萄', '苹果', '黄瓜', '西瓜'] reverse: ['西瓜', '黄瓜', '苹果', '葡萄'] pop: ['西瓜', '黄瓜', '苹果'] popitem 葡萄 pop: ['黄瓜', '苹果'] popitem 西瓜 clear: [] sort: [3, 11, 17, 20, 26, 52, 59, 60, 79, 92] sort(reverse): [92, 79, 60, 59, 52, 26, 20, 17, 11, 3]
# 切片 l = list('近观山有色,细听水无声') print(l[0]) print(l[-1]) print(l[1:5]) print(l[:]) print(l[::2]) print(l[::-1]) l = [1, 2, 3.5, '列表', True, ["儿子", ['孙子', 3]]] print(l[-1][0]) print(l[-1][1][0])
近 声 ['观', '山', '有', '色'] ['近', '观', '山', '有', '色', ',', '细', '听', '水', '无', '声'] ['近', '山', '色', '细', '水', '声'] ['声', '无', '水', '听', '细', ',', '色', '有', '山', '观', '近'] 儿子 孙子
# 长度 最大值 最小值 l = [17, 92, 79, 11, 26, 60, 3, 52, 20, 59] print('len: ', len(l)) print('max: ', max(l)) print('min: ', min(l))
len: 10 max: 92 min: 3
# 迭代 l = list('问君能有几多愁?') for i in l: print(i, end = ' ') pass
问 君 能 有 几 多 愁 ?
l = list(range(1, 10)) print('range(1, 10): ', l) print('range(10): ', list(range(10))) print('range(1, 10, 2): ', list(range(1, 10, 2))) print('range(1, 10, -1):', list(range(10, 1, -1))) for i in range(10): print(i, end=' ')
range(1, 10): [1, 2, 3, 4, 5, 6, 7, 8, 9] range(10): [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] range(1, 10, 2): [1, 3, 5, 7, 9] range(1, 10, -1): [10, 9, 8, 7, 6, 5, 4, 3, 2] 0 1 2 3 4 5 6 7 8 9
l = list('春华秋月何时了,往事知多少') for index, value in enumerate(l): print('%s->%s' % (index, value), end=',')
l1 = list('北风券地百草折') l2 = list('胡天八月即飞雪') print(list(zip(l1, l2))) for x, y in zip(l1, l2): print(x, y )
[('北', '胡'), ('风', '天'), ('券', '八'), ('地', '月'), ('百', '即'), ('草', '飞'), ('折', '雪')]
北 胡
风 天
券 八
地 月
百 即
草 飞
折 雪
# 切片修改 l = ['华为', 'vivo', '三星', '小米'] del l[-1] print(l) l[0] = 'iphone' print(l) l[2:] = ['诺基亚', 'oppp'] print(l)
['华为', 'vivo', '三星'] ['iphone', 'vivo', '三星'] ['iphone', 'vivo', '诺基亚', 'oppp']
# 运算 + * in l1 = ['淘宝', '京东'] l2 = ['新浪', '腾迅'] print(l1 + l2) print(l1 * 3) print('百度' in l1)
['淘宝', '京东', '新浪', '腾迅'] ['淘宝', '京东', '淘宝', '京东', '淘宝', '京东'] False
# 列表赋值 l1 = list('安得xx千万间大庇天下寒士俱欢颜') print('l1: ', l1) l2 = l1 l2[2:4] = "广厦" print('l2: ', l2) print('l1: ', l1) l1: ['安', '得', 'x', 'x', '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜'] l2: ['安', '得', '广', '厦', '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜'] l1: ['安', '得', '广', '厦', '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜']
# 列表复制-浅拷贝1 l1 = list('安得xx千万间大庇天下寒士俱欢颜') print('l1: ', l1) l2 = l1.copy() # l2 = l1[:] l2[2:4] = "广厦" print('l2: ', l2) print('l1: ', l1) l1: ['安', '得', 'x', 'x', '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜'] l2: ['安', '得', '广', '厦', '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜'] l1: ['安', '得', 'x', 'x', '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜']
# 列表复制-浅拷贝2 l1 = ['安', '得', ['x', 'x'], '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜'] print('l1: ', l1) l2 = l1[:] # l2 = l1.copy() l2[2][0] = "广" l2[2][1] = "厦" print('l2: ', l2) print('l1: ', l1) l1: ['安', '得', ['x', 'x'], '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜'] l2: ['安', '得', ['广', '厦'], '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜'] l1: ['安', '得', ['广', '厦'], '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜']
# 列表复制-深拷贝 import copy l1 = ['安', '得', ['x', 'x'], '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜'] print('l1: ', l1) l2 = copy.deepcopy(l1) l2[2][0] = "广" l2[2][1] = "厦" print('l2: ', l2) print('l1: ', l1) l1: ['安', '得', ['x', 'x'], '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜'] l2: ['安', '得', ['广', '厦'], '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜'] l1: ['安', '得', ['x', 'x'], '千', '万', '间', '大', '庇', '天', '下', '寒', '士', '俱', '欢', '颜']
4. 元组 tuple
元组和列表的含义几乎是一致的,唯一区别是元组是不可修改的类型
这意味着,元组在定义的时候要规定好每个元素的值,之后就不可以修改元素了
所有列表的操作中涉及元素变动的方法也都不可以使用
元组用圆括号包起来表示, 并用逗号分割
t = (1, 2, 3,)
值得一提的是,如果元组中只有一个元素,必须在元素后面加上逗号
其实定义元组的时候 ,逗号很重要,括号反而是可以省略的
#不是元组,是数字1 t = (1) # 是一个单元素的元组 t = (1, ) # 定义元组,可以省略括号 t = 1, 2, 3
由于元组不可修改元素,所以列表方法的变动元素的方法都不可以使用了
元组,只支持 index, count 这两个方法
通用方法中都和列表一致,但注意,还是不能变动元素,不能删除,修改元素
t = (1, 2, 2, 3, 5 ) print(t[0], t[-1], t[1:3], t[::-1]) print(len(t), max(t), min(t)) for item in t: print(item, end=',') print(t.index(3)) print(t.count(2)) # 不支持的操作 # del t[0] # t[2] = 666 # t.append(7)
5. 字典
列表可以看作是元素的顺序容器,我们通过下标来访问其中的元素。
字典也是一个容器,只不过我们是通过一个不可变的值,去访问另一个值
不可变的值,我们称为key,就是键的意思
真正可变化的数据,我们称为 value ,就是值的意思
所以字典可以说是由 一个个 键-值 对组成的
我们通过 键,可以访问 到值
字典的元素由 大括号括起来,同样使用逗号分割
每一个元素,由键-值组成,键和值之间用冒号分开
employee = { 'name' : '王富贵', 'age' : 18, 'gender': '男', 'address': "深圳市宝安区西乡街道", 'marry' : False, 'hobby' : ['冲浪', '翻船'] }
字典方法
获取键集合 keys()
获取值集合 values()
获取键值元组 items()
根据key获取值 get
根据一组key创建字典 fromkeys
删除并获取值 pop, popitem
设置默认值 setdefault
更新 update
# 字典方法 employee = { 'name' : '王富贵', 'age' : 18, 'gender': '男', 'address': "深圳市宝安区西乡街道", 'marry' : False, 'hobby' : ['冲浪', '翻船'] } # 获取所有键 keys() print( employee.keys()) # 获取所有值集合 values() print( employee.values()) # 获取所有键值对 items() print( employee.items()) # 根据key获取值, 没有对应的值就返回default get(k, [default]) print(employee.get('gender', '未知')) print(employee.get('salary', 1000)) # 根据一组key 创建字典 fromkeys(iterable, [default]) d = dict.fromkeys('12345', 'default') print(d) # 按键删除一个键值对,并获取值 pop(k, [default]) d = { 1: '111', 2: '222', 3: '3333'} print(d.pop(1, '没有')) print(d.pop(1, '没有')) # 随机删除一个键值对并返回,如果没有就报错 popitem() print(d.popitem()) print(d.popitem()) print(d.popitem()) # 设置一个不存在的key默认值,如果存在key不操作 setdefault(k, [default]) d = { 'name': '王富贵'} print(d.setdefault('age', 18)) print(d) print(d.setdefault('age', 28)) print(d) # 更新字典 # D.update([E, ]**F) -> None. Update D from dict/iterable E and F. # If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] # If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v # In either case, this is followed by: for k in F: D[k] = F[k] d = {'name':'王富贵'} d.update({'age':18}) print(d) d.update([('gender', '男'), ('salary', 1300)]) print(d) d.update(marry=True, hobby=['翻船', '潜水']) print(d)
通用方法
字典是一种无序的容器,可以用key取值
字典同样可以获取长度,是指字典中键值对的个数
对字典使用max, min方法,默认是比较key的大小
字典同样可以迭代
字典是可以被修改的类型
# 通用方法 # 字典是可以被修改的类型 # 字典是一种无序的容器,可以用key取值 person = {'name': '王富贵', 'age': 18, 'gender': '男', 'salary': 1300, 'marry': True, 'hobby': ['翻船', '冲浪']} print(person['age']) # 字典同样可以获取长度,是指字典中键值对的个数 print(len(person)) # 对字典使用max, min方法,默认是比较key的大小 print(max(person), min(person)) # 字典同样可以迭代 for k, v in person.items(): print("%s -> %s"% (k, v)) for k in person: print("%s -> %s"% (k, person[k])) # 字典可以被修改 del person['salary'] print(person) person['marry'] = False print(person)
思考 字典和列表的区别
列表 有序,顺序访问,偏移量访问一个值,只有按偏移量访问时速度 快
字典 无序,一个值去访问另一个值 访问速度快,占用内存大一些
5. 总结
数据类型归类
可修改
列表,字典
不可修改
整数,布尔,字符串,元组
顺序访问:
字符串,列表,元组
无序访问 :
字典
直接访问 :
整数,布尔
容器类型:
列表,元组,字典
原子类型:
整数,布尔,字符串

浙公网安备 33010602011771号