Python 基础数据类型补充以及编码

举报
Yuchuan 发表于 2019/11/13 23:15:47 2019/11/13
【摘要】 对Python基数数据类型的补充

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

1.1 字符串

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

# capitalize,swapcase,title
name = "hello woRld XiaoXiao"
print(name.capitalize())  # 首字母大写
print(name.swapcase())  # 大小写翻转
msg = 'this is shenzhen'
print(msg.title())  # 每个单词的首字母大写

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

# 寻找字符串中的元素是否存在
str4 = "you are don't is lea!"
ret3 = str4.find("don't", 0, 13)
print(ret3)  # 返回的找到的元素的索引,如果找不到返回-1


ret4 = str4.index("don't", 0, 13)
print(ret4)  # 返回的找到的元素的索引,找不到报错。

1.2 元组

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

tu = (8)
print(tu, type(tu))  # 8 <class 'int'>

tu1 = ('yuchuan')
print(tu1, type(tu1))  # 'yuchuan' <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 = ('yuchuanduan',)
print(tu1, type(tu1))  # ('yuchuanduan',) <class 'tuple'>

tu2 = ([1, 2, 3],)
print(tu2, type(tu2))  # ([1, 2, 3],) <class 'tuple'>

 结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
8 <class 'int'>
yuchuan <class 'str'>
[1, 2, 3] <class 'list'>
(1,) <class 'tuple'>
('yuchuanduan',) <class 'tuple'>
([1, 2, 3],) <class 'tuple'>

Process finished with exit code 0

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

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

tu = ('皇帝', [1, 2, 3, 8, ], 'lao', '嫦娥')
print(tu.index('皇帝'))

print(tu.index('皇后'))

结果:

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
Traceback (most recent call last):
0
  File "/home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py", line 55, in <module>
    print(tu.index('皇后'))
ValueError: tuple.index(x): x not in tuple

Process finished with exit code 1

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

tu = ("于传段", "于传段", "于传段", "于传段", "丽丽", "华华",)
print(tu.count("于传段"))  # 4

1.3 列表

列表的其他操作方法:

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

str1 = ["q", "w", "q", "q", "q", "r", "t", "y"]
print(str1.count("q"))  # 4

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

str1 = ["q", "w", "r", "t", "y"]
print(str1.index("t"))

print(str1.index("p"))

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
0
Traceback (most recent call last):
  File "/home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py", line 69, in <module>
    print(str1.index("p"))
ValueError: 'p' is not in list

Process finished with exit code 1

使用index的方法找列表的元素,如果有,返回元素的索引位置,如果没有则会报错。

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

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

list1 = [2, 1, 3, 4, 5, 8, 42, 11]

list1.sort()  # 他没有返回值,所以只能打印a
print(list1)

list1.reverse()  # 他也没有返回值,所以只能打印a
print(list1)

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
[1, 2, 3, 4, 5, 8, 11, 42]
[42, 11, 8, 5, 4, 3, 2, 1]

Process finished with exit code 0

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

list1 = [1, 2, 3, 5, 6, 8, 9]
list2 = [4, 5, 6, 8, 7]

print(list1 + list2)
print(list1 * 3)

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
[1, 2, 3, 5, 6, 8, 9, 4, 5, 6, 8, 7]
[1, 2, 3, 5, 6, 8, 9, 1, 2, 3, 5, 6, 8, 9, 1, 2, 3, 5, 6, 8, 9]

Process finished with exit code 0

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

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

有列表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 所以你在往下进行循环时,就会发现,额........完全不对了。

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

直接删除

list1 = [1, 2, 3, 5, 6, 8, 9]
index = 0
for i in list1:
    if index % 2 != 0:
        list1.remove(i)
    index += 1
print(list1)

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
[1, 3, 5, 8, 9]

Process finished with exit code 0

倒叙删除

list1 = [1, 2, 3, 5, 6, 8, 9]
index = 0
for i in list1[::-1]:
    if index % 2 != 0:
        list1.remove(i)
    index += 1
print(list1)

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
[1, 3, 6, 9]

Process finished with exit code 0

所以,我们要总结一下:

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

1.4 dict

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

# popitem 3.5版本之前,popitem为随机删除,3.6之后为删除最后一个,有返回值
dic = {'name': '于传', 'age': 28}
ret = dic.popitem()
print(ret, dic)

# update
dic = {'name': '华英', 'age': 18}
dic.update(sex='女', height=165)
print(dic)

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

dic1 = {"name": "lili", "age": 19, "sex": "male"}
dic2 = {"name": "xiaoqiaoying", "weight": 55}
dic1.update(dic2)
print(dic1)
print(dic2)

# 字典增删改查的补充

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
('age', 28) {'name': '于传'}
{'name': '华英', 'age': 18, 'sex': '女', 'height': 165}
{'name': '华英', 'age': 18, 1: 'a', 2: 'b', 3: 'c', 4: 'd'}
{'name': 'xiaoqiaoying', 'age': 19, 'sex': 'male', 'weight': 55}
{'name': 'xiaoqiaoying', 'weight': 55}

Process finished with exit code 0

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

dic = dict.fromkeys('hello', '于传')
print(dic)

dic = dict.fromkeys([1, 2, 3, 4, 5], '华英')
print(dic)

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

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
{'h': '于传', 'e': '于传', 'l': '于传', 'o': '于传'}
{1: '华英', 2: '华英', 3: '华英', 4: '华英', 5: '华英'}
140313081891656 140313081891656 140313081891656
{1: [666], 2: [666], 3: [666]}

Process finished with exit code 0

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

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

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

dic = {'k1': '于传', 'k2': '华英', 'k3': '肖肖', 'age': 18}
for item in dic:
    if 'k' in item:
        del dic[item]
print(dic)

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
Traceback (most recent call last):
  File "/home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py", line 149, in <module>
    for item in dic:
RuntimeError: dictionary changed size during iteration

Process finished with exit code 1

翻译过来是:字典在循环迭代时,改变了大小。

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



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

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

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

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

int bool  str 三者转换

# int ---> bool
i = 1000
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 = 200
print(str(i1))  # '200'

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

# str ---> bool
s1 = '于传'
s2 = ''
print(bool(s1))  # True 非空即True
print(bool(s2))  # False
# bool ---> str
t1 = True
print(str(True))  # 'True'

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
True
False
1
0
200
80
True
False
True

Process finished with exit code 0

str list 两者转换

# str ---> list
s1 = '华英 于传 肖肖'
print(s1.split())

# list ---> str  # 前提 list 里面所有的元素必须是字符串类型才可以
l1 = ['于传', '华英', '肖肖']
print(' '.join(l1))

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
['华英', '于传', '肖肖']
于传 华英 肖肖

Process finished with exit code 0

list set 两者转换

# list ---> set
lst1 = [1, 2, 3, 4, 5, 7, 8, 9]
print(set(lst1))

# set ---> list
set1 = {1, 2, 3, 3, 66, 53, 87}
print(list(set1))

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
{1, 2, 3, 4, 5, 7, 8, 9}
[1, 2, 3, 66, 53, 87]

Process finished with exit code 0

str bytes 两者转换

# str ---> bytes
s1 = '于传'
print(s1.encode('utf-8'))

# bytes ---> str
b = b'\xe4\xba\x8e\xe4\xbc\xa0'
print(b.decode('utf-8'))

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
b'\xe4\xba\x8e\xe4\xbc\xa0'
于传

Process finished with exit code 0

所有数据都可以转化成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 等)保存到文件。

1573739521985216.png



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

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

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

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

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

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

咱们就以网络传输为例:

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

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

1573740081848716.png



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

1573740228491586.png

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

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

class bytes(object):
    """
    bytes(iterable_of_ints) -> bytes
    bytes(string, encoding[, errors]) -> bytes
    bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer
    bytes(int) -> bytes object of size given by the parameter initialized with null bytes
    bytes() -> empty bytes object
    
    Construct an immutable array of bytes from:
      - an iterable yielding integers in range(256)
      - a text string encoded using the specified encoding
      - any object implementing the buffer API.
      - an integer
    """
    def capitalize(self): # real signature unknown; restored from __doc__
        """
        B.capitalize() -> copy of B
        
        Return a copy of B with only its first character capitalized (ASCII)
        and the rest lower-cased.
        """
        pass

    def center(self, width, fillchar=None): # real signature unknown; restored from __doc__
        """
        B.center(width[, fillchar]) -> copy of B
        
        Return B centered in a string of length width.  Padding is
        done using the specified fill character (default is a space).
        """
        pass

    ......
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进制。很不方便。

str1 = '于传段'
print(str1.encode("utf-8"))

str1 = b'\xe4\xba\x8e\xe4\xbc\xa0\xe6\xae\xb5'

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

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

str ----> bytes

# encode称作编码:将 str 转化成 bytes类型
str1 = '祖国'
b1 = str1.encode('utf-8')  # 转化成utf-8的bytes类型
print(str1)
print(b1)

str1 = '祖国'
b1 = str1.encode('gbk')  # 转化成gbk的bytes类型
print(str1)
print(b1)

结果

/home/yuchuan/YuchuanData/PythonData/PythonProject/venv/bin/python /home/yuchuan/YuchuanData/PythonData/PythonProject/python_fuction.py
祖国
b'\xe7\xa5\x96\xe5\x9b\xbd'
祖国
b'\xd7\xe6\xb9\xfa'

Process finished with exit code 0

bytes ---> str

# decode称作解码, 将 bytes 转化成 str类型
b1 = b'\xe7\xa5\x96\xe5\x9b\xbd'
str1 = b1.decode('utf-8')
print(str1)  # 祖国

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

str1 = "祖国"

print(str1.encode('utf-8'))
print(str1.encode('gbk'))

b1 = b'\xe7\xa5\x96\xe5\x9b\xbd'  # 这是utf-8编码bytes类型的祖国
b2 = b'\xd7\xe6\xb9\xfa'  # 这是gbk编码bytes类型的祖国

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

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

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

 看下面的图就行了!

1573742297945401.png











【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。