数据类型
导读
大家好,很高兴又和大家见面啦!!!
在上一篇内容中我们介绍了Python中的常量与变量的相关内容。常量也就是不可改变的量,与之对应的变量则是可以改变的量。
Python中的常量可以分为四类:
- 数字常量
- 字符串常量
- 布尔常量
- 特殊常量——None
而Python中的变量与C/C++中的变量不一样的是,在Python中变量在定义时是不需要指明数据类型的,变量的数据类型会根据定义变量时的初始值来进行确定。
计算机语言作为人类与计算机交流的工具,它的作用就是用来给计算机下达相关的指令来使计算机执行相关的操作。
程序猿在使用计算机语言与计算机进行沟通时,则需要通过所使用的语言来描述想要传达的信息。
就比如描述一个人的年龄可以通过整数来描述;描述一个人的姓名可以通过字符串来描述;描述一件衣服的价格可以通过浮点数来描述;描述一件事的真假可以通过布尔值来描述……
这里就涉及到了我们在描述这些数据时所对应的数据类型,在C语言中,我们已经接触到的数据类型可以分为以下几个大类:
- 整型数据类型
- 浮点型数据类型
- 指针型数据类型
- 数组型数据类型
- 布尔型数据类型
- 自定义数据类型
而这些大类中又会分为几个小类,这里我们以整型和浮点型为例,这里我们不考虑无符号数据类型:
- 整型可分为:
- 字符型数据类型(
char
) - 短整型数据类型(
short
) - 整型数据类型(
int
) - 长整型数据类型(
long int
) - 更长的整型数据类型(
long long int
)
- 字符型数据类型(
- 浮点型可分为:
- 单精度浮点型数据类型(
float
) - 双精度浮点型数据类型(
double
)
- 单精度浮点型数据类型(
从这里我们可以看到,C 语言这种面向过程的计算机语言在语法上是非常的精细的,通过C语言我们可以很详细的描述一件事情发生的经过,但是相对应的,在处理同一件事情上,C语言的代码量是相比于其它语言更加庞大的,因此C语言无法处理特别复杂的问题。
C++作为面向对象的计算机语言,它相比于C语言则是能够处理更加高度抽象化的问题,因此在C++中舍弃了C语言中的部分数据类型,如指针类型。
那么在Python中,其数据类型又会和C/C++之间有哪些不同之处呢?在今天的内容中我们将会介绍Python中的数据类型。
一、数据类型的分类
Python 作为一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言,它相比于C/C++而言,代码的可读性更强,描述事物的过程更加直接,因此在Python中,其数据类型主要有以下几类:
- Number(数字)
- String(字符串)
- bool(布尔类型)
- List(列表)
- Tuple(元组)
- Set(集合)
- Dictionary(字典)
在这七种数据类型中,根据其对应类型的值是否可变可以将其分为两类:
- 不可变类型——数字、字符串、布尔、元组这四种数据类型的值是不可变的;
- 可变类型——列表、集合、字典中这三种数据类型的值是可变的。
这里所说的可变可不变,我们通过具体的代码来进行理解:
# 数据类型 a = 1 # 数字(Number) b = 'A' # 字符串(String) c = True # 布尔(bool) tup = (a, b, c) # 元组(Tuple)
在代码中,我们分别展示了这四种类型的变量以及这些变量所对应的值,我们在描述数字、字符串、和布尔这三种数据类型的值时,实际上说的是这些数据类型的常量值,这些常量值是不可变的;
而对于元组而言,它相比于C语言中的数组来说在存储数据这一块的能力要更加的强大,元组中的数据可以是不同类型的数据,但是一旦元组中的数据确定后,就无法再对这些数据进行修改,如下所示:
可以看到,此时程序是会报错——类型错误:元组类型不支持项分配。这就好比于位于元组中的值被打包成为了一个常量,和我们在C语言中接触的常量字符串一样,常量字符串中的值是无法被修改的。
对于列表、字典、集合而言,它们的值则是可以进行修改的,如下所示:
lis = [a, b, c] # 列表(List) dic = {a: 1, b: 'A', c: True} # 字典(Dictionary) Set = {a, b, c} # 集合(Set)
这里我们列举了这三种数据类型的变量及其对应的值,这些变量我们可以理解为是元组类型的升级版,如果说将元组类型看做是常量字符串的话,那这里的三种类型就可以理解为字符数组。
在C/C++中,常量字符串中的字符是无法在后续的运行中进行更改的,而字符数组中的值则是可以在后续的运行中进行修改,如下所示:
可以看到,此时我们可以完成对字符数组中的元素的修改,但是无法修改常量字符串中的元素。
在前面我们也说过,元组我们可以理解为常量字符串,元组中的元素就行常量字符串中的元素一样,是无法进行修改的,而列表、字典和集合这三种类型的变量就如同字符数组一样,我们可以对其值进行修改,这里我以列表为例,如下所示:
从测试结果中可以看到,此时列表中的值在经过修改后发生了变化。相信大家现在应该理解了什么是值可变,什么是值不可变,这里我们就不再继续展开。
1.1 Number(数字)
Python中的数字主要可以分为三种数据类型:
整型(
int
)——通常被称为是整型或整数,是正或负整数,不带小数点。布尔(bool)是整型的子类型。浮点型(
float
) - 浮点型由整数部分与小数部分组成,浮点型也可以使用科学计数法表示( 2.5 e 2 = 2.5 × 1 0 2 = 250 2.5e2 = 2.5 × 10^2 = 250 2.5e2=2.5×102=250)复数(
complex
)- 复数由实数部分和虚数部分构成,可以用a + bj
,或者complex(a,b)
表示, 复数的实部a和虚部b都是浮点型。
对于Python而言,为了使编程语言简洁化,保证解决问题的方式只有一种,因此Python中舍弃了C语言中的字符型(char
)、短整型(short
)、长整型(long
)、更长的整型(long long
)这些表示整型的数据类型,只保留了整型(int
),通过int
来表示所有类型的整型;对于浮点型而言,Python同样舍弃了双精度浮点型(double
),只保留了单精度浮点型(float
),通过float
来表示所有类型的小数。
这时可能有朋友就会问了,那如果舍弃了这些数据类型,此时int
所包含的数值范围是多少呢?会不会出现溢出的情况呢?
这个问题就涉及到了两个概念——静态数据类型与动态数据类型。
1.1.1 静态数据类型
所谓的静态数据类型,简单的理解就是不可改变的数据类型,如C/C++中的数据类型。
当我定义一个整型变量之后,那该变量就只能是整型,相对应的该变量的取值范围就是 − 2 31 ~ 2 31 − 1 -2^{31}~2^{31}-1 −231~231−1,具体的值我们可以在VS中通过头文件<limits.h>
中获取,如下所示:
一个整型变量的值就是一个周期函数,当值达到最小值后再减1就会回到最大值,当值达到最大值后再加1就会回到最小值,如下所示:
在C/C++中所有的数据类型都是如此,每一个数据类型所创建的变量只能存储其对应的数值范围内的数,该存储范围是不能发生改变的,也就是说其变量的类型不会根据存储的值的大小而产生变化;
静态数据类型除了变量的取值范围不会改变外,其变量的数据类型也不会发生改变,如下所示:
在这次测试中,我们将整型变量a赋值了一个字符串,整型变量b赋值了一个双精度浮点型小数。
- 从打印结果可以看到,字符串是能够正常打印,但是双精度浮点型的小数无法打印;
- 从监视窗口可以看到,即使我们此时赋予变量a和变量b的值一个为字符类型一个为双精度浮点型,但是变量a和变量b的数据类型并没有因此发生改变。
从以上两个例子可以得到结论以下结论:
- 静态数据类型的变量的取值范围不会改变;
- 静态数据类型的变量的数据类型不会改变;
这里有朋友可能就会好奇了,为什么将字符串赋予整型变量不会对结果产生影响?
- 这是因为字符类型同样也是整型的一个分支,只不过其字节大小比整型小;
- 将字符串赋值给整型变量,就相当于将短整型的数据赋值给整型变量,因此二者并不会发生冲突。
1.1.2 动态数据类型
与静态数据类型相对应的就是动态数据类型。
动态数据类型与静态数据类型刚好相反,动态数据类型的变量的取值范围会随着存储值的大小而发生改变,动态数据类型的变量也会因为其值的数据类型的变化而发生变化。
在Python中创建的变量就属于动态数据类型的变量,如下所示:
从这里的测试结果不难发现,在Python中变量的数据类型、取值范围会随着值的不同而发生变化。因此对于Python而言,其变量的数据类型为动态数据类型,并且其变量具有以下特点:
- 变量的取值范围可视为负无穷大到正无穷大;
- 变量的数据类型会根据其存储值的数据类型的改变而改变
1.2 String(字符串)
在C/C++中,字符类型属于整型的一个小分支,字符串类型为指针类型的一个小分支。在C/C++中,整型和指针类型都是能够进行±整数的类型,因此C/C++可以实现字符+整数,字符串+整数,如下所示:
在C/C++中,字符±整数实际上是字符对应的ASCII码值±整数;字符串±整数实际上是字符串的地址进行±整数。
但是在Python中不同类型的变量是无法进行+运算的,这里的不同类型指的是前面我们提到的七种类型,但是对于同一类型的不同分支则是可以进行运算的,如下所示:
但是如果是不同类型的变量,则无法进行+运算,如下所示:
因此,在Python中,舍弃了C/C++中的字符类型,而重新创建了一个新的数据类型——字符串类型。
字符串类型的值既可以用单引号''
表示,也可以用双引号""
表示。因此Python中就没有了字符和字符串之分,所有用单引号或者双引号表示的对象都被划分为了字符串类型。
1.3 bool(布尔类型)
在C语言中,我们通过引用头文件<stdbool.h>
之后,就可以解锁布尔类型。
C/C++中的布尔类型的值有两个——真(true
)和假(false
)。布尔类型的值常用于判断语句中,如下所示:
在条件语句中,当判断语句的结果为真,则执行对应的分支中的语句。从上例可以看到,因为a的布尔值为真,所以执行的是if
语句中的内容,而b的值为假,所以执行的是else
语句中的内容。
在Python中布尔类型的值同样也是两个——真(True
)和假(False
)。
这里要注意的是Python中的布尔值的首字母是大写,而C/C++中布尔值的首字母是小写。
Python中布尔型被归为了整型的一个分支,但是其使用方式与C/C++中一致,都是用于判断语句中,如下所示:
对于布尔类型而言,不管是C/C++还是Python,布尔值的判断都满足:
- 0为假,值为0;
- 非0为真,值为1
也就是说布尔值在进行整型运算时,真对应的整型值就是1,假对应的整型值就是0,如下所示:
还有其他的数据类型我们会在后面的篇章中再着重介绍,这里就不再展开,目前只需要了解即可。接下来我们就需要继续学习Python中的数据类型之间是如何相互转换的。
二、数据类型的转换
在C语言中我们在介绍操作符时有提到过一个概念——隐式类型转换和显示类型转换。
简单的理解就是在不同类型的值进行运算时,运算的过程中自动进行类型转换的现象称为隐式类型转换,通过强制类型转换操作符完成转换的现象称为显式类型转换。
如果有不了解的朋友可以回顾以下【C语言必学知识点四】操作符中的十二、表达式求值的相关内容,里面有详细介绍C语言中的隐式类型转换,这里就不再展开。
而在Python中同样也有隐式类型转换和显示类型转换一说。
2.1 隐式类型转换
在Python中,隐式类型转换主要出现同类型的不同分支中,如下所示:
在这次测试中我们分别测试了整型与布尔型、整型与浮点型、浮点型与复数型这同一大类的数据类型下的三种情况下不同类型的值的运算,从测试结果中我们可以看到,整型与布尔型的值相加得到的新值e的数据类型为整型,整型与浮点型的值相加得到的新值c的数据类型为浮点型,浮点型的值与复数型的值相加得到的新值的数据类型为复数型。
隐式转换的规则为:在同一大类的不同分支的数据类型的值进行运算时,较小的数据类型会优先转换成较大的数据类型。
在这整个运算过程中,不同类型的值进行相加时,实际上为了保证不丢失数据,较小的数据类型都会先通过隐式转换的方式变成较大的数据类型在与之进行运算。
因此我们不难得到在Number中的这些数据类型的大小关系为:
b o o l < i n t < f l o a t < c o m p l e x bool < int < float < complex bool<int<float<complex
2.2 显式类型转换
在C/C++中为了实现不同类型的数据之间的运算,是通过强制类型转换操作符才能得以实现,如下所示:
可以看到在C语言中取模操作符是无法用于double类型的操作对象,此时我们就需要通过强制类型转换操作符将double类型的对象强制转换为整型,如下所示:
可以看到此时程序就能正常运行。
像C/C++这种为了完成不同类型的数据之间的运算,将其中一种类型强制转换成另一种类型的方式就是显式类型转换。
C/C++中的显式类型转换是通过强制类型转换操作符()
来实现,而在Python中则是通过内建函数来实现。Python中用于进行类型转换的函数如下所示:
对于不同的函数如何进行使用,大家可以参考Python3 数据类型转换,里面有详细的介绍。这里我给大家简单的介绍几个我们会用到的内建函数;
2.2.1 int(x[,base])
——将x转换为一个base进制的整数
该函数的语法如下所示:
int(x, base=10) # x——转换的对象(字符串或者数字) # base——转换的进制(默认十进制)
从函数的语法中可知,该函数仅用于将字符串或者数字转换成base进制的整数,具体的进制由传入的参数base来决定,base的默认参数为10,也就是说,我们如果不对base传参的情况下,函数默认将x转换成十进制的整数,如下所示:
可以看到在打印的结果中,虽然a与b的值都是打印的10,但是一个为字符串,一个为整数。当我们对函数传入第二个参数后,其值则变为了2,也就是说函数将"10"
转换成了2进制的整数。
那是不是说该函数只需要传入一个或者两个参数就够了呢?然而这个函数并不是这么简单,我们要给函数传入的参数需要根据base来决定。
对于不同进制而言,其取值范围如下所示:
进制 | 取值范围 |
---|---|
二进制 | 0~1 |
八进制 | 0~7 |
十进制 | 0~9 |
十六进制 | 0~9与a~f |
下面我们以十六进制为例来进行测试:
可以看到此时函数是能够正常的进行转换的,如果转换的字符串中存在一个不在范围内的字符,又会有什么结果呢?
可以看到此时程序再次运行后,就出现了值错误的提示。这还没完,如果我们将参数改为整型又会如何呢?
可以看到,此时又出现了类型错误。函数不能转换非字符串的内容。
之所以会有这种结果,是因为该函数的底层逻辑是将数字或字符串转换成十进制的整数,而非是进行不同进制的相互转换。
也就是说,当我们要将字符串转换成不同进制的整数时,我们首先需要保证字符串的内容符合要转换的进制的取值范围,其次,在转换的过程中,函数会先通过相应的进制来识别字符串中的内容,最后,函数会将识别到的内容转换为十进制的整数。
这也就是为什么第一次测试中对于字符串"123456789abcdef"
转换之后得到的是一个很大的数,而非十六进制格式的结果;
该函数的操作数可以为数字,实际上就是进行的一个取整的工作,如下所示:
可以看到,该取整的过程实际上是取得参数的整数部分,因此该函数更多的情况下是用于字符串转整数,这个在后面的内容中会详细说明,这里就不再继续展开。
相信大家现在应该能够理解Python中的数据类型以及类型之间的转换了,在后面的学习中,我们会对这一块的内容继续深入的学习,这里就不再继续展开。
结语
今天的内容到这里就全部结束了,在下一篇内容中我们将介绍《Python中的输入与输出》的相关内容,大家记得关注哦!如果大家喜欢博主的内容,可以点赞、收藏加评论支持一下博主,当然也可以将博主的内容转发给你身边需要的朋友。最后感谢各位朋友的支持,咱们下一篇再见!!!