七. 基础数据类型补充内容

你离开我真会死。 提交于 2019-11-30 11:30:47

一. 基础数据类型补充内容

1.1 字符串

字符串咱们之前已经讲了一些非常重要的方法,剩下还有一些方法虽然不是那么重要,但是也算是比较常用,在此给大家在补充一些,需要大家尽量记住。

复制代码
#captalize,swapcase,title
print(name.capitalize()) #首字母大写
print(name.swapcase()) #大小写翻转
msg='taibai say hi'
print(msg.title()) #每个单词的首字母大写

# 内同居中,总长度,空白处填充
ret2 = a1.center(20,"*")  
print(ret2)


#寻找字符串中的元素是否存在
# ret6 = a4.find("fjdk",1,6)
# print(ret6)  # 返回的找到的元素的索引,如果找不到返回-1

# ret61 = a4.index("fjdk",4,6)
# print(ret61) # 返回的找到的元素的索引,找不到报错。
复制代码

1.2 元组

python中元组有一个特性,元组中如果只含有一个元素且没有逗号,则该元组不是元组,与改元素数据类型一致,如果有逗号,那么它是元组。

复制代码
tu = (1)
print(tu,type(tu))  # 1 <class 'int'>
tu1 = ('alex')
print(tu1,type(tu1))  # 'alex' <class 'str'>
tu2 = ([1, 2, 3])
print(tu2,type(tu2))  # [1, 2, 3] <class 'list'>

tu = (1,)
print(tu,type(tu))  # (1,) <class 'tuple'>
tu1 = ('alex',)
print(tu1,type(tu1))  # ('alex',) <class 'tuple'>
tu2 = ([1, 2, 3],)
print(tu2,type(tu2))  # ([1, 2, 3],) <class 'tuple'>
复制代码

元组也有一些其他的方法:

index:通过元素找索引(可切片),找到第一个元素就返回,找不到该元素即报错。

tu = ('太白', [1, 2, 3, ], 'WuSir', '女神')
print(tu.index('太白')) # 0

count: 获取某元素在列表中出现的次数

tu = ('太白', '太白', 'WuSir', '吴超')
print(tu.count('太白')) # 2

1.3 列表

列表的其他操作方法:

count(数)(方法统计某个元素在列表中出现的次数)。

1 a = ["q","w","q","r","t","y"]
2 print(a.count("q"))

index(方法用于从列表中找出某个值第一个匹配项的索引位置)

1 a = ["q","w","r","t","y"]
2 print(a.index("r"))

sort (方法用于在原位置对列表进行排序)。

 reverse (方法将列表中的元素反向存放)。

1 a = [2,1,3,4,5]
2 a.sort()# 他没有返回值,所以只能打印a
3 print(a)
4 a.reverse()#他也没有返回值,所以只能打印a
5 print(a)

列表也可以相加与整数相乘

l1 = [1, 2, 3]
l2 = [4, 5, 6]
# print(l1+l2)  # [1, 2, 3, 4, 5, 6]
print(l1*3)  # [1, 2, 3, 1, 2, 3, 1, 2, 3]

循环列表,改变列表大小的问题

先不着急,说这个问题,先做一道小题:

有列表l1, l1 = [11, 22, 33, 44, 55],请把索引为奇数对应的元素删除(不能一个一个删除,此l1只是举个例子,里面的元素不定)。

有人说这个还不简单么?我循环列表,然后进行判断,只要他的索引为奇数,我就删除。OK,你可以照着这个思路去做。

那么根据题意,这个题最终的结果应该是:l1 = [11, 33, 55],但是你得到的结果却是: l1 = [11, 33, 44] 为什么不对呢???

用这个进行举例:当你循环到22时,你将列表中的22删除了,但是你带来的影响是:33,44,55都会往前进一位,他们的索引由原来的2,3,4变成了1,2,3 所以你在往下进行循环时,就会发现,额........完全不对了。

那这个怎么解决呢?有三种解决方式:

想看? 门都没有,课上听吧。
你觉得我会写答案么?
哈哈,就不告诉你。

所以,我们要总结一下:

在循环一个列表时的过程中,如果你要改变列表的大小(增加值,或者删除值),那么结果很可能会出错或者报错。

 1.4 dict

首先是字典的增删改查有几个方法需要给大家讲解一下:

复制代码
#popitem 3.5版本之前,popitem为随机删除,3.6之后为删除最后一个,有返回值
dic = {'name': '太白', 'age': 18}
ret = dic.popitem()
print(ret,dic) # ('age', 18) {'name': '太白'}


# update
dic = {'name': '太白', 'age': 18}
dic.update(sex='男', height=175)
print(dic) # {'name': '太白', 'age': 18, 'sex': '男', 'height': 175}

dic = {'name': '太白', 'age': 18}
dic.update([(1, 'a'),(2, 'b'),(3, 'c'),(4, 'd')])
print(dic) # {'name': '太白', 'age': 18, 1: 'a', 2: 'b', 3: 'c', 4: 'd'}

dic1 = {"name":"jin","age":18,"sex":"male"}
dic2 = {"name":"alex","weight":75}
dic1.update(dic2)
print(dic1) # {'name': 'alex', 'age': 18, 'sex': 'male', 'weight': 75}
print(dic2) # {'name': 'alex', 'weight': 75} 
复制代码

fromkeys:创建一个字典:字典的所有键来自一个可迭代对象,字典的值使用同一个值。

复制代码
# dic = dict.fromkeys('abcd','太白')
# print(dic) # {'a': '太白', 'b': '太白', 'c': '太白', 'd': '太白'}
#
# dic = dict.fromkeys([1, 2, 3],'太白')
# print(dic) # {1: '太白', 2: '太白', 3: '太白'}

# 这里有一个坑,就是如果通过fromkeys得到的字典的值为可变的数据类型,那么你的小心了。
dic = dict.fromkeys([1, 2, 3], [])
dic[1].append(666)
print(id(dic[1]),id(dic[2]),id(dic[3]))  # {1: [666], 2: [666], 3: [666]}
print(dic)  # {1: [666], 2: [666], 3: [666]}
复制代码

循环字典,改变字典大小的问题

来,先来研究一个小题,有如下字典:

dic = {'k1':'太白','k2':'barry','k3': '白白', 'age': 18} 请将字典中所有键带k元素的键值对删除。那么拿到这个题,有人说我一个一个删除,这是不行的,因为这个字典只是举个例子,里面的元素不确定,所以你要怎么样?你要遍历所有的键,符合的删除,对吧? 嗯,终于上套了,哦不,上道了,请开始你的表演。

复制代码
dic = {'k1':'太白','k2':'barry','k3': '白白', 'age': 18}
for i in dic:
    if 'k' in i:
        del dic[i]
print(dic)

你会发现,报错了。。。。。
错误原因:
RuntimeError: dictionary changed size during iteration
翻译过来是:字典在循环迭代时,改变了大小。
复制代码

这是什么意思? 他的意思很简单,你的字典在循环时,不要改变字典的大小,只要改变大小,就会报错!那么怎么解决???

哈哈哈哈哈,天真。

所以说,他和列表差不多,只不过比列表更暴力一些,对其进行总结就是:

在循环一个字典的过程中,不要改变字典的大小(增,删字典的元素),这样会直接报错。

二. 数据类型间的转换问题

咱们现在学过的数据类型有:int bool str list tuple dict set ,这些数据类型之间都存在着相互转换的问题,有些转换是非常重要的,那么有些转换则基本不用,那么接下来我们学习一下比较重要的数据的转换问题。

int bool  str 三者转换

复制代码
# int ---> bool
i = 100
print(bool(i))  # True  # 非零即True
i1 = 0
print(bool(i1))  # False 零即False

# bool ---> int
t = True
print(int(t))  # 1  True --> 1
t = False
print(int(t))  # 0  False --> 0

# int ---> str
i1 = 100
print(str(i1))  # '100'

# str ---> int  # 全部由数字组成的字符串才可以转化成数字
s1 = '90'
print(int(s1))  # 90

# str ---> bool
s1 = '太白'
s2 = ''
print(bool(s1))  # True 非空即True
print(bool(s2))  # False
# bool ---> str
t1 = True
print(str(True))  # 'True'
复制代码

str list 两者转换

复制代码
# str ---> list
s1 = 'alex 太白 武大'
print(s1.split())  # ['alex', '太白', '武大']

# list ---> str  # 前提 list 里面所有的元素必须是字符串类型才可以
l1 = ['alex', '太白', '武大']
print(' '.join(l1))  # 'alex 太白 武大'
复制代码

list set 两者转换

复制代码
# list ---> set
s1 = [1, 2, 3]
print(set(s1))

# set ---> list
set1 = {1, 2, 3, 3,}
print(list(set1))  # [1, 2, 3]
复制代码

str bytes 两者转换

复制代码
# str ---> bytes
s1 = '太白'
print(s1.encode('utf-8'))  # b'\xe5\xa4\xaa\xe7\x99\xbd'

# bytes ---> str
b = b'\xe5\xa4\xaa\xe7\x99\xbd'
print(b.decode('utf-8'))  # '太白'
复制代码

所有数据都可以转化成bool值

转化成bool值为False的数据类型有:
'', 0, (), {}, [], set(), None

剩下的一些数据类型也可以互相转化,在这里我就不一一介绍了。

三.基础数据类型的总结

按存储空间的占用分(从低到高)

复制代码
数字
字符串
集合:无序,即无序存索引相关信息
元组:有序,需要存索引相关信息,不可变
列表:有序,需要存索引相关信息,可变,需要处理数据的增删改
字典:有序,需要存key与value映射的相关信息,可变,需要处理数据的增删改(3.6之后有序)
复制代码

按存值个数区分

标量/原子类型 数字,字符串
容器类型 列表,元组,字典

 

 

 

按可变不可变区分

可变 列表,字典
不可变 数字,字符串,元组,布尔值

 

 

 

按访问顺序区分

直接访问 数字
顺序访问(序列类型) 字符串,列表,元组
key值访问(映射类型) 字典

  

 

 

 

 

四. 编码的进阶

前两天咱们已经讲了编码,我相信大家对编码有一定的了解了,那么,咱们先回顾一下:

首先来说,编码即是密码本,编码记录的就是二进制与文字之间的对应关系,现存的编码本有:

ASCII码:包含英文字母,数字,特殊字符与01010101对应关系。

  a  01000001  一个字符一个字节表示。

GBK:只包含本国文字(以及英文字母,数字,特殊字符)与0101010对应关系。

  a  01000001  ascii码中的字符:一个字符一个字节表示。

  中 01001001 01000010  中文:一个字符两个字节表示。

 Unicode包含全世界所有的文字与二进制0101001的对应关系。

  a  01000001 01000010 01000011 00000001        

  b  01000001 01000010 01100011 00000001        

  中 01001001 01000010 01100011 00000001

UTF-8:包含全世界所有的文字与二进制0101001的对应关系(最少用8位一个字节表示一个字符)。

     a   01000001  ascii码中的字符:一个字符一个字节表示。

  To 01000001 01000010   (欧洲文字:葡萄牙,西班牙等)一个字符两个字节表示。

  中  01001001 01000010 01100011  亚洲文字;一个字符三个字节表示。

 简单回顾完编码之后,再给大家普及一些知识点:

  1. 在计算机内存中,统一使用Unicode编码,当需要将数据保存到硬盘或者需要网络传输的时候,就转换为非Unicode编码比如:UTF-8编码。

  其实这个不用深入理解,他就是规定,举个例子:用文件编辑器(word,wps,等)编辑文件的时候,从文件将你的数据(此时你的数据是非Unicode(可能是UTF-8,也可能是gbk,这个编码取决于你的编辑器设置))字符被转换为Unicode字符读到内存里,进行相应的编辑,编辑完成后,保存的时候再把Unicode转换为非Unicode(UTF-8,GBK 等)保存到文件。

 

  2. 不同编码之间,不能直接互相识别。

  比如你的一个数据:‘老铁没毛病’是以utf-8的编码方式编码并发送给一个朋友,那么你发送的肯定是通过utf-8的编码转化成的二进制01010101,那么你的朋友接收到你发的这个数据,他如果想查看这个数据必须将01010101转化成汉字,才可以查看,那么此时那也必须通过utf-8编码反转回去,如果要是通过gbk编码反转,那么这个内容可能会出现乱码或者报错。

那么了解完这两点之后,咱们开始进入编码进阶的最重要的内容。

前提条件:python3x版本(python2x版本与这个不同)。

主要用途:数据的存储或者传输。

刚才咱们也说过了,在计算机内存中,统一使用Unicode编码,当需要将数据保存到硬盘或者需要网络传输的时候,就转换为非Unicode编码比如:UTF-8编码。

咱们就以网络传输为例:

  好那么接下来咱们继续讨论,首先先声明一个知识点就是这里所说的'数据',这个数据,其实准确的说是以字符串(特殊的字符串)类型的数据。那么有同学就会问到,python中的数据类型很多,int bool list dict str等等,如果我想将一个列表数据通过网络传输给小明同学,不行么? 确切的说不行,你必须将这个列表转化成一个特殊的字符串类型,然后才可以传输出去,数据的存储也是如此。

  那么你就清楚一些了,你想通过存储或者网络传输的数据是一个特殊的字符串类型,那么我就直接将这个字符串传出去不就行了么?比如我这有一个数据:'今晚10点吃鸡,大吉大利' 这不就是字符串类型么?我直接将这个数据通过网络发送给小明不就可以了么?不行。这里你还没有看清一个问题,就是特殊的字符串。为什么?

那么这个解决方式是什么呢?

那么这个bytes类型是个什么类型呢?其实他也是Python基础数据类型之一:bytes类型。

这个bytes类型与字符串类型,几乎一模一样,可以看看bytes类型的源码,bytes类型可以用的操作方法与str相差无几.

 bytes类型的源码

那么str与bytes类型到底有什么区别和联系呢,接下来咱们以表格的形式给你做对比。

类名 str类型 bytes类型 标注
名称 str,字符串,文本文字 bytes,字节文字 不同,可以通过文本文字或者字节文字加以区分
组成单位 字符 字节 不同
组成形式 '' 或者 "" 或者 ''' ''' 或者 """ """ b'' 或者 b""  或者 b''' ''' 或者 b""" """ 不同,bytes类型就是在引号前面+b(B)大小写都可以
表现形式

英文: 'alex' 

中文: '中国'

英文:b'alex'

中文:b'\xe4\xb8\xad\xe5\x9b\xbd'

字节文字对于ascii中的元素是可以直接显示的,

但是非ascii码中的元素是以十六进制的形式表示的,不易看出。

编码方式 Unicode 可指定编码(除Unicode之外)比如UTF-8,GBK 等 不同
相应功能 upper lower spllit 等等 upper lower spllit 等等 几乎相同
转译 可在最前面加r进行转译 可在最前面加r进行转译 相同
重要用途 python基础数据类型,用于存储少量的常用的数据

  负责以二进制字节序列的形式记录所需记录的对象,

至于该对象到底表示什么(比如到底是什么字符)

则由相应的编码格式解码所决定。

Python3中,bytes通常用于网络数据传输、

二进制图片和文件的保存等等

bytes就是用于数据存储和网络传输数据
更多 ...... ......  

 那么上面写了这么多,咱们不用全部记住,对于某些知识点了解一下即可,但是对于有些知识点是需要大家理解的:

bytes类型也称作字节文本,他的主要用途就是网络的数据传输,与数据存储。那么有些同学肯定问,bytes类型既然与str差不多,而且操作方法也很相似,就是在字符串前面加个b不就行了,python为什么还要这两个数据类型呢?我只用bytes不行么?

如果你只用bytes开发,不方便。因为对于非ascii码里面的文字来说,bytes只是显示的是16进制。很不方便。

s1 = '中国'
b1 = b'\xe4\xb8\xad\xe5\x9b\xbd'  # utf-8 的编码

好,上面咱们对于bytes类型应该有了一个大致的了解,对str 与 bytes的对比也是有了对比的了解,那么咱们最终要解决的问题,现在可以解决了,那就是str与bytes类型的转换的问题。

如果你的str数据想要存储到文件或者传输出去,那么直接是不可以的,上面我们已经图示了,我们要将str数据转化成bytes数据就可以了。

str ----> bytes

复制代码
# encode称作编码:将 str 转化成 bytes类型
s1 = '中国'
b1 = s1.encode('utf-8')  # 转化成utf-8的bytes类型
print(s1)  # 中国
print(b1)  # b'\xe4\xb8\xad\xe5\x9b\xbd'

s1 = '中国'
b1 = s1.encode('gbk')  # 转化成gbk的bytes类型
print(s1)  # 中国
print(b1)  # b'\xd6\xd0\xb9\xfa'
复制代码

bytes ---> str

# decode称作解码, 将 bytes 转化成 str类型
b1 = b'\xe4\xb8\xad\xe5\x9b\xbd'
s1 = b1.decode('utf-8')
print(s1)  # 中国

那么这里还有一个最重要的,也是你们以后工作中经常遇到的让人头疼的问题,就是gbk编码的数据,转化成utf-8编码的数据。有人说老师,我怎么有点蒙呢?这是什么? 来,捋一下,bytes类型他叫字节文本,他的编码方式是非Unicode的编码,非Unicode即可以是gbk,可以是UTF-8,可以是GB2312..... 

b1 =  b'\xe4\xb8\xad\xe5\x9b\xbd'  # 这是utf-8编码bytes类型的中国
b2 =  b'\xd6\xd0\xb9\xfa'   # 这是gbk编码bytes类型的中国

那么gbk编码的bytes如何转化成utf-8编码的bytes呢? 

不同编码之间,不能直接互相识别。

上面我说了,不同编码之间是不能直接互相是别的,这里说了不能直接,那就可以间接,如何间接呢? 现存世上的所有的编码都和谁有关系呢? 都和万国码Unicode有关系,所以需要借助Unicode进行转换。

 看下面的图就行了!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!