Python3_数据类型和变量
一、数据类型
在Python中,能够直接处理的数据类型有以下几种:
1、整数
Python中的整数类型与数学中的整数概念一致,它可正可负没有取值范围限制(只是理论上的无限,实际上机器内存有限,不可能无限大)。
整数类型的四种表现方式:
二进制:以0b或0B开头,例如0b010,-0B101
八进制:以0o或0O开头,例如0o123,-0O456
十进制:不做说明和演示
十六进制:以0x或0X开头,例如0x9a,-0X89
2、浮点数
Python中的浮点数与数学中的实数概念一致,它指的是带有小数点以及小数的数字。与整数不同,浮点数的取值范围和小数精度都存在限制,但常规计算时可以忽略。
浮点数取值范围从数量级上讲大约是-10^308~10^308,精度数量级约为10^-16,也就是说两个小数之间的差别最小可以表示到10^-16这个数量级。
但是浮点数有一个特性需要特别注意:浮点数间运存存在不确定尾数,这不是BUG。这里举一个例子0.1+0.2应该得出的是0.3,但是Python计算出来的却不是0.3,如下:
>>> 0.1+0.2
0.30000000000000004
>>> 0.1+0.5
0.6
其实这个不确定尾数并不止Python中存在,许多编程语言中都存在,它涉及到了计算机对数字运算的内部实现原理。
Python使用的IEEE 754标准(52M/11E/1S),该标准采用8字节的64位二进制存储空间,分配了52位来存储浮点数的有效数字,11位存储指数,1位存储正负号(也是Python常说的53位二进制表示小数部分,52+1,2^53-2=9007199254740990,约为10^16),即这是一种二进制版的科学计数法格式。
还需要了解十进制小数与二进制小数之间互相转换问题,首先来看一下十进制小数转换为二进制小数:
原十进制小数为0.1
0.1*2=0.2——取整数部分填充当前二进制小数位——0——剩余非零部分用于继续运算——0.2
0.2*2=0.4——取整数部分填充当前二进制小数位——0——剩余非零部分用于继续运算——0.4
0.4*2=0.8——取整数部分填充当前二进制小数位——0——剩余非零部分用于继续运算——0.8
0.8*2=1.6——取整数部分填充当前二进制小数位——1——剩余非零部分用于继续运算——0.6
0.6*2=1.2——取整数部分填充当前二进制小数位——1——剩余非零部分用于继续运算——0.2
......之后进入无限循环
但是到了Python中并不能无限循环,从第53位开始进行舍入,舍入规则为0舍1入,那么0.1转换为二进制小数实际为0.00011001100110011001100110011001100110011001100110011010。注意:4个二进制为一个整体。
二进制小数转换为十进制小数:
原二进制小数为0.00011001100110011001100110011001100110011001100110011010
0*2^-1+
0*2^-2+
0*2^-3+
1*2^-4+
1*2^-5+
0*2^-6+
......
1*2^-53+
0*2^-54+
1*2^-55+
0*2^-56=
0.10000000000000000055511151231257827021181583404541015625
可以看到经过两次转行后出现了非常长的尾数,只是在浮点数输出时只输出了前16位小数。所以我们可以得出一个结论,二进制表示小数,可以无限接近,但不完全相同。这也是不确定尾数产生的原因,在运算时会先将十进制转换为二进制,再进行运算,运算完成后再由二进制转换为十进制。
随之也带来了另一个问题,运算后的数值比较。由于不确定尾数的存在,不能直接进行比较,必须使用round(x,d)函数,对数值x进行四舍五入,d为小数精确位数。
>>> 0.1+0.2==0.3
False
>>> round(0.1+0.2,1)==0.3
True
Python浮点数可以使用字母e或E作为幂的符号,以10为基数的科学计数法,格式为e,表示a*10^b。例如96000,采用科学计数法就是9.6e4;0.0043,采用科学计数法就是4.3E-3。
3、字符串
字符串是以单引号’或双引号"括起来的任意文本,比如’123’,“qwe"等等。请注意,’'或”“本身只是一种表示方式,不是字符串的一部分,因此,字符串’abc’只有a,b,c这3个字符。如果’本身也是一个字符,那就可以用”"括起来,比如"This’ me!"包含的字符是T,h,i,s,’,空格,m,e,这8个字符。
如果字符串内部既包含’又包含"怎么办?可以用转义字符\来标识,比如:
"This’\"me\"!"
表示的字符串内容是This’“me”!
转义字符\可以转义很多字符,比如\n表示换行,\t表示制表符,字符\本身也要转义,所以\表示的字符就是\,可以在Python的交互式命令行用print()打印字符串看看:
> > a = "This’\"me\"!"
>> > print(a)
运行结果:
This’"me"!
>> > print('I\'m learning\nPython3。')
运行结果:
I'm learning
Python3。
>> > print('\\\n\\')
运行结果:
\
\
如果字符串里面有很多字符都需要转义,就需要加很多\,为了简化,Python还允许用r’‘表示’'内部的字符串默认不转义,可以自己试试:
>>> print(r'\\\\\\\n\\\\')
运行结果:
\\\\\\\n\\\\
如果字符串内部有很多换行,用\n写在一行里不好阅读,为了简化,Python允许用’’’…’’'的格式表示多行内容:
>>> print('''
今天还挺忙
云云说我没和她说早上好
然后给我记了小本本''')
运行结果:
今天还挺忙
云云说我没和她说早上好
然后给我记了小本本
4、布尔值
布尔值和布尔代数的表示完全一致,一个布尔值只有True、False两种值,要么是True,要么是False,在Python中,可以直接用True、False表示布尔值(请注意大小写),也可以通过布尔运算计算出来:
>>> True
True
>>> False
False
>>> 1<2
True
>>> 2<1
False
布尔值可以用and、or和not运算。
and运算是与运算,只有所有都为True,and运算结果才是True
>>> True and True
True
>>> True and False
False
>>> False and False
False
>>> 5 > 6 and 32> 1
False
or运算是或运算,只要其中有一个为True,or运算结果就是True:
>>> True or True
True
>>> True or False
True
>>> False or False
False
not运算是非运算,它是一个单目运算符,把True变成False,False变成True:
>>> not True
False
>>> not False
True
布尔值经常用在条件判断中,比如:
age=11
if age >= 18:
print('adult')
else:
print('teenager')
运行结果:
teenager
5、空值
空值是Python里一个特殊的值,用None表示。None不能理解为0,因为0是有意义的,而None是一个特殊的空值。
二、变量
变量的概念基本上和初中代数的方程变量是一致的,只是在计算机程序中,变量不仅可以是数字,还可以是任意数据类型。
变量在程序中就是用一个变量名表示了,变量名必须是大小写英文、数字和_的组合,且不能用数字开头,比如:
a = 1
变量a是一个整数
a = '1'
变量1是一个字符串。
a = True
变量a是一个布尔值True。
这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。例如Java是静态语言,赋值语句如下(// 表示注释):
int a = 123; // a是整数类型变量
a = "ABC"; // 错误:不能把字符串赋给整型变量
和静态语言相比,动态语言更灵活,就是这个原因。
赋值语句的等号不等同于数学的等号。比如下面的代码:
x = 1
x = x + 1
如果从数学上理解x = x + 1那无论如何是不成立的,在程序中,赋值语句先计算右侧的表达式x + 1,得到结果2,再赋给变量x。由于x之前的值是1,重新赋值后,x的值变成2。
最后,理解变量在计算机内存中的表示也非常重要。当我们写:
a="qwe123"
时,Python解释器干了两件事情:
在内存中创建了一个’qwe123’的字符串;
在内存中创建了一个名为a的变量,并把它指向’qwe123’。
也可以把一个变量a赋值给另一个变量b,这个操作实际上是把变量b指向变量a所指向的数据,例如下面的代码:
# -*- coding: utf-8 -*-
a= 'ABC'
b = a
a = 'XYZ'
print("a=",a,"b=",b)
运行结果:
a= XYZ b= ABC
最后一行打印出变量b的内容到底是’ABC’呢还是’def’?如果从数学意义上理解,就会错误地得出b和a相同,也应该是’def’,但实际上b的值是’ABC’一行一行分析下代码:
执行a = 'ABC',解释器创建了字符串'ABC'和变量a,并把a指向'ABC':
执行b = a,解释器创建了变量b,并把b指向a指向的字符串'ABC':
执行a = 'XYZ',解释器创建了字符串'XYZ',并把a的指向改为'XYZ',但b并没有更改: