运行结果:
f1Value: 12.5
f1Type: <class ‘float’>
f2Value: 0.34557808421257
f2Type: <class ‘float’>
f3Value: 8.47e-26
f3Type: <class ‘float’>
f4Value: 3.456797451324568e+26
f4Type: <class ‘float’>
f5Value: 120000.0
f5Type: <class ‘float’>
f6Value: 1.2300000000000002
f6Type: <class ‘float’>
从运行结果可以看出,Python 能容纳极小和极大的浮点数。print 在输出浮点数时,会根据浮点数的长度和大小适当的舍去一部分数字,或者采用科学计数法。
f5 的值是 120000,但是它依然是小数类型,而不是整数类型。
让人奇怪的是 f6,`12.3*0.1`的计算结果很明显是 1.23,但是 print 的输出却不精确。这是因为小数在内存中是以二进制形式存储的,小数点后面的部分在转换成二进制时很有可能是一串无限循环的数字,无论如何都不能精确表示,所以小数的计算结果一般都是不精确的。有兴趣的读者请猛击下面的链接深入学习:
* [进制转换:二进制、八进制、十六进制、十进制之间的转换]( )
* [小数在内存中是如何存储的,揭秘诺贝尔奖级别的设计(长篇神文)]( )
## Python复数类型(complex)详解
复数(Complex)是 [Python]( ) 的内置类型,直接书写即可。换句话说,Python 语言本身就支持复数,而不依赖于标准库或者第三方库。
复数由实部(real)和虚部(imag)构成,在 Python 中,复数的虚部以`j`或者`J`作为后缀,具体格式为:
a + bj
a 表示实部,b 表示虚部。
【实例】Python 复数的使用:
c1 = 12 + 0.2j
print("c1Value: ", c1)
print(“c1Type”, type(c1))
c2 = 6 - 1.2j
print("c2Value: ", c2)
#对复数进行简单计算
print("c1+c2: ", c1+c2)
print("c1*c2: ", c1*c2)
运行结果:
c1Value: (12+0.2j)
c1Type <class ‘complex’>
c2Value: (6-1.2j)
c1+c2: (18-1j)
c1\*c2: (72.24-13.2j)
可以发现,复数在 Python 内部的类型是 complex,Python 默认支持对复数的简单计算。
## Python浮点数精度问题(包含解决方案)
前面章节提到,Python 中浮点类型之间的运算,其结果并不像我们想象的那样,例如:
>>> 0.1+0.2
0.30000000000000004
>>> 0.1+0.1-0.2
0.0
>>> 0.1+0.1+0.1-0.3
5.551115123125783e-17
>>> 0.1+0.1+0.1-0.2
0.10000000000000003
为什么在计算这么简单的问题上,计算机会出现这样的低级错误呢?真正的原因在于十进制和数和二进制数的转换。
我们知道,计算机其实是不认识十进制数,它只认识二进制数,也就是说,当我们以十进制数进行运算的时候,计算机需要将各个十进制数转换成二进制数,然后进行二进制间的计算。
以类似 0.1 这样的浮点数为例,如果手动将其转换成二进制,其结果为:
0.1(10)=0.00011001100110011…(2)
可以看到,结果是无限循环的,也就是说,0.1 转换成二进制数后,无法精确到等于十进制数的 0.1。同时,由于计算机存储的位数是有限制的,所以如果要存储的二进制位数超过了计算机存储位数的最大值,其后续位数会被舍弃(舍弃的原则是“0 舍 1 入”)。
>
> 这种问题不仅在 Python 中存在,在所有支持浮点数运算的编程语言中都会遇到,它不光是 Python 的 Bug。
>
>
>
明白了问题产生的原因之后,那么该如何解决呢?就 Python 的浮点数运算而言,大多数计算机每次计算误差不会超过 253,这对于大多数任务来说已经足够了。
如果需要非常精确的结果,可以使用 decimal 模块(其实就是别人开发好的程序,我们可以直接拿来用),它实现的十进制数运算适合会计方面的应用和有高精度要求的应用。例如:
#使用模块前,需要使用 import 引入
import decimal
a = decimal.Decimal(“10.0”)
b = decimal.Decimal(“3”)
print(10.0/3)
print(a/b)
运行结果为:
3.3333333333333335
3.333333333333333333333333333
可以看到,相比普通运算的结果,使用 decimal 模块得到的结果更精确。
如果 decimal 模块还是无法满足需求,还可以使用 fractions 模块,例如:
#引入 decimal 模块
from fractions import Fraction
print(10/3)
print(Fraction(10,3))
运行结果为:
3.3333333333333335
10/3
可以看到,通过 fractions 模块能很好地解决浮点类型数之间运算的问题。
>
> 本节涉及到了有关模块的使用,读者不用研究细节,会用即可,后续章节会详细介绍模块。
>
>
>
## Python字符串详解(包含长字符串和原始字符串)
若干个字符的集合就是一个字符串(String)。[Python]( ) 中的字符串必须由双引号`" "`或者单引号`' '`包围,具体格式为:
“字符串内容”
‘字符串内容’
字符串的内容可以包含字母、标点、特殊符号、中文、日文等全世界的所有文字。
下面都是合法的字符串:
* “123789”
* “123abc”
* “http://c.biancheng.net/python/”
* “C语言中文网成立8年了”
Python 字符串中的双引号和单引号没有任何区别。而有些编程语言的双引号字符串可以解析变量,单引号字符串一律原样输出,例如 [PHP]( ) 和 [JavaScript]( )。
### 处理字符串中的引号的
当字符串内容中出现引号时,我们需要进行特殊处理,否则 Python 会解析出错,例如:
‘I’m a great coder!’
由于上面字符串中包含了单引号,此时 Python 会将字符串中的单引号与第一个单引号配对,这样就会把`'I'`当成字符串,而后面的`m a great coder!'`就变成了多余的内容,从而导致语法错误。
对于这种情况,我们有两种处理方案:
##### 1) 对引号进行转义
在引号前面添加反斜杠`\`就可以对引号进行转义,让 Python 把它作为普通文本对待,例如:
str1 = ‘I’m a great coder!’
str2 = “引文双引号是”,中文双引号是“"
print(str1)
print(str2)
运行结果:
I’m a great coder!
引文双引号是",中文双引号是“
##### 2) 使用不同的引号包围字符串
如果字符串内容中出现了单引号,那么我们可以使用双引号包围字符串,反之亦然。例如:
str1 = “I’m a great coder!” #使用双引号包围含有单引号的字符串
str2 = ‘引文双引号是",中文双引号是“’ #使用单引号包围含有双引号的字符串
print(str1)
print(str2)
运行结果和上面相同。
### 字符串的换行
Python 不是格式自由的语言,它对程序的换行、缩进都有严格的语法要求。要想换行书写一个比较长的字符串,必须在行尾添加反斜杠`\`,请看下面的例子:
s2 = ‘It took me six months to write this Python tutorial.
Please give me more support.
I will keep it updated.’
上面 s2 字符串的比较长,所以使用了转义字符`\`对字符串内容进行了换行,这样就可以把一个长字符串写成多行。
另外,Python 也支持表达式的换行,例如:
num = 20 + 3 / 4 +
2 * 3
print(num)
### Python长字符串
在《[Python注释]( )》一节中我们提到,使用三个单引号或者双引号可以对多行内容进行注释,这其实是 Python 长字符串的写法。所谓长字符串,就是可以直接换行(不用加反斜杠`\`)书写的字符串。
Python 长字符串由三个双引号`"""`或者三个单引号`'''`包围,语法格式如下:
“”“长字符串内容”""
‘’‘长字符串内容’’’
在长字符串中放置单引号或者双引号不会导致解析错误。
如果长字符串没有赋值给任何变量,那么这个长字符串就不会起到任何作用,和一段普通的文本无异,相当于被注释掉了。
注意,此时 Python 解释器并不会忽略长字符串,也会按照语法解析,只是长字符串起不到实际作用而已。
当程序中有大段文本内容需要定义成字符串时,优先推荐使用长字符串形式,因为这种形式非常强大,可以在字符串中放置任何内容,包括单引号和双引号。
【实例】将长字符串赋值给变量:
longstr = ‘’‘It took me 6 months to write this Python tutorial.
Please give me a to ‘thumb’ to keep it updated.
The Python tutorial is available at http://c.biancheng.net/python/.’‘’
print(longstr)
长字符串中的换行、空格、缩进等空白符都会原样输出,所以你不能写成下面的样子:
longstr = ‘’’
It took me 6 months to write this Python tutorial.
Please give me a to ‘thumb’ to keep it updated.
The Python tutorial is available at http://c.biancheng.net/python/.
‘’’
print(longstr)
虽然这样写格式优美,但是输出结果将变成:
It took me 6 months to write this Python tutorial.
Please give me a to ‘thumb’ to keep it updated.
The Python tutorial is available at http://c.biancheng.net/python/.
字符串内容前后多出了两个空行,并且每一行的前面会多出四个空格。
### Python原始字符串
Python 字符串中的反斜杠`\`有着特殊的作用,就是转义字符,例如上面提到的`\'`和`\"`,我们将在《[Python转义字符]( )》一节中详细讲解,这里大家先简单了解。
转义字符有时候会带来一些麻烦,例如我要表示一个包含 Windows 路径`D:\Program Files\Python 3.8\python.exe`这样的字符串,在 Python 程序中直接这样写肯定是不行的,不管是普通字符串还是长字符串。因为`\`的特殊性,我们需要对字符串中的每个`\`都进行转义,也就是写成`D:\\Program Files\\Python 3.8\\python.exe`这种形式才行。
这种写法需要特别谨慎,稍有疏忽就会出错。为了解决转义字符的问题,Python 支持原始字符串。在原始字符串中,`\`不会被当作转义字符,所有的内容都保持“原汁原味”的样子。
在普通字符串或者长字符串的开头加上`r`前缀,就变成了原始字符串,具体格式为:
str1 = r’原始字符串内容’
str2 = r""“原始字符串内容”""
将上面的 Windows 路径改写成原始字符串的形式:
rstr = r’D:\Program Files\Python 3.8\python.exe’
print(rstr)
##### 原始字符串中的引号
如果普通格式的原始字符串中出现引号,程序同样需要对引号进行转义,否则 Python 照样无法对字符串的引号精确配对;但是和普通字符串不同的是,此时用于转义的反斜杠会变成字符串内容的一部分。
请看下面的代码:
str1 = r’I’m a great coder!’
print(str1)
输出结果:
I’m a great coder!
需要注意的是,Python 原始字符串中的反斜杠仍然会对引号进行转义,因此原始字符串的结尾处不能是反斜杠,否则字符串结尾处的引号会被转义,导致字符串不能正确结束。
在 Python 中有两种方式解决这个问题:一种方式是改用长字符串的写法,不要使用原始字符串;另一种方式是单独书写反斜杠,这是接下来要重点说明的。
例如想表示`D:\Program Files\Python 3.8\`,可以这样写:
str1 = r’D:\Program Files\Python 3.8’ ‘\’
print(str1)
我们先写了一个原始字符串`r'D:\Program Files\Python 3.8'`,紧接着又使用`'\\'`写了一个包含转义字符的普通字符串,Python 会自动将这两个字符串拼接在一起ÿ