对象是Python最基本的概念之一,在Python中的一切都是对象,常用的内置对象如表1.3.1.1所示。除此之外,还有大量的标准库对象和扩展库对象,标准库是Python默认安装的,但需要导入之后才能使用其中的对象,扩展库对象则需要先安装扩展库然后再导入并使用其中的对象。在Python中可以创建任意类型的变量,一般情况与对象的概念不作严格的区分。
对象类型 | 示例 | 简要说明 |
数字 | 1234,3.14,1.3e5,3 + 4j | 数字大小没有限制,且支持复数及其运算 |
字符串 | 'swfu',"I love China",'''Python''' | 字符串使用单引号、双引号、三引号作为界定符 |
列表 | [1,2],['a','b',['c',2]] | 所有元素放在一对方括号中,元素之间使用逗号分隔 |
字典 | {1:'food,2:'taste',3:'import'} | 所有元素放在一对大括号中,元素之间使用逗号分隔,元素形式为“键:值” |
元组 | (2,-5,6) | 所有元素放在一对圆括号中,元素之间使用逗号分隔 |
文件 | f=open('data.dat','rb') | open是Python内置函数,使用指定的模式打开文件 |
集合 | set(a,b,c),{'a','b','c'} | 所有元素放在一对大括号中,元素之间使用逗号分隔,元素不允许重复 |
布尔型 | True,False | |
空类型 | None | |
编程单元 |
函数(使用def定义) 类(使用class定义) |
类和函数都属于可调用对象 |
表1.3.1.1
在Python中,不需要想Java那样事先声明变量名及其类型,直接赋值即可创建各种类型的对象变量,并且变量的类型是可以改变的。例如,语句:
>>> x = 3
创建了整型变量 x , 并赋值为3
>>> x = 'Hello World'
创建了字符串变量 x , 并赋值为“Hello World”
>>> x = [1,2,3]
创建了列表对象 x , 并赋值为[1,2,3]。这一点同样适用于元组、字典、集合以及Python其他任意类型的对象,以及自定义类型的对象。
虽然不需要再使用之前显式地声明变量机器类型,但是Python仍属于强类型编程语言,Python解释器会根据赋值来自动推断变量类型。每种类型的对象支持的运算也不完全一样,因此在使用变量时需要程序员自己确定所进行的运算是否合适,以免出现异常或者意料之外的结果。Python还是一种动态类型语言,也就是说,变量的类型可以随时变化。如下代码块1.3.1.1所示:
1 >>> x = 3
2 >>> print(type(x)) #内置函数type用来返回变量类型
3 <class 'int'>
4 >>>
5 >>> x = 'Hello World'
6 >>> print(type(x))
7 <class 'str'>
8 >>>
9 >>> x = [1,2,3]
10 >>> print(type(x))
11 <class 'list'>
12 >>>
13 >>> isinstance(3,int) #内置函数 isinstance()用来测试对象是否为指定类型的实例
14 True
15 >>>
16 >>> isinstance('Hello World',str)
17 True
18 >>>
代码块1.3.1.1
代码块1.3.1.1中首先创建了整型变量 x ,然后又分别创建了字符串和列表类型的变量 x 。当创建了煮饭吃类型的变量 x 之后,之前创建的整型变量 x 自动失效;创建列表对象 x 只有,之前创建的字符串变量 x 自动失效。可以将该模型理解为“状态机”,除非显式修改变量类型或删除变量,否则变量将一直保持之前的类型。
小提示:在Python中可以使用变量表示任意大的数字,不用担心范围的问题,但是对于浮点数的计算由于精确度的问题偶尔可能会出现略显奇葩的结果。如代码块1.3.1.2所示:
1 >>> 9999 ** 99 #这里 ** 是幂乘运算符 2 990148353526723487602263124753282625570559528895791057324326529121794837894053513464
422176826916433932586924386677766244032001623756821400432975051208820204980098735552703
841362304669970510691243800218202840374329378800694920309791954185117798434329591212159
106298699938669908067573374724331208942425544893910910073205049031656789220889560732962
926226305865706593594917896276756396848514900989999 3 >>> 4 >>> 0.3 + 0.2 #实数相加 5 0.5 6 >>> 7 >>> 0.4 - 0.1 #实数相减 8 0.30000000000000004 #这个结果很奇怪吧,我再补充一篇文章来介绍这个吧 9 >>> 10 >>> 0.4 - 0.1 == 0.3 11 False 12 >>>
代码块1.3.1.2
Python支持复数运算,如代码块1.3.1.3所示:
1 >>> x = 3 + 4j #使用 j 或 J 表示复数虚部
2 >>> y = 5 + 6j
3 >>>
4 >>> #复数之间的加、减、乘、除
5 >>> x + y
6 (8+10j)
7 >>> x - y
8 (-2-2j)
9 >>> x * y
10 (-9+38j)
11 >>> x / y
12 (0.6393442622950819+0.03278688524590165j)
13 >>>
14 >>> abs(x) #复数的模
15 5.0
16 >>> x.imag #复数的虚部
17 4.0
18 >>> x.real #复数的实部
19 3.0
20 >>> x.conjugate() #复数 x 的共轭复数
21 (3-4j)
22 >>>
代码块1.3.1.3
拓展知识:
拓展一:Python标准库 fractions中的Fraction 对象支持分数运算,如代码块1.3.1.4所示:
1 >>> from fractions import Fraction
2 >>> x = Fraction(3,5) #创建分数
3 >>> y = Fraction(3,7)
4 >>> x
5 Fraction(3, 5)
6 >>> x.numerator #分子
7 3
8 >>> x.denominator #分母
9 5
10 >>>
11 >>> #分数之间的四则运算,支撑通分
12 >>> x + y
13 Fraction(36, 35)
14 >>>
15 >>> x - y
16 Fraction(6, 35)
17 >>>
18 >>> x * y
19 Fraction(9, 35)
20 >>>
21 >>> x / y
22 Fraction(7, 5)
23 >>>
24 >>> x * 2 #分数与数字之间的运算
25 Fraction(6, 5)
26 >>>
代码块1.3.1.4
拓展二:Python decimal模块 解决浮点数运算的精确度问题
1 >>> 0.1 + 0.1 + 0.1 == 0.3
2 False
3 >>>
4 >>> 0.1 + 0.1 + 0.1
5 0.30000000000000004
7 >>>
8 >>> #什么情况,不相等啊
9 >>>
10 >>> #可见Python中的浮点数的存储是不精确的。
11 >>> #因为Python内置的二进制浮点数实现float是不精确的,这是二进制的问题。
12 >>> #不过直观看上去,二进制浮点数与实际数值的差距很小。但金融应用、科学计算等需要精确十进制表达的场合就不行了,为了确保十进制表达的场合就不行了,为了确保十进制数位精度,或者用户希望计算结果与手算相符的场合。Decimal重现了手工的数学运算。高精度使Decimal可以执行二进制浮点数无法进行的模运算和等值测试。
13 >>>
14 >>> #下面正式进入decimal模块的学习
15 >>> from decimal import Decimal
16 >>> Decimal('7.1') / Decimal('3.1')
17 Decimal('2.290322580645161290322580645')
18 >>>
19 >>> #(1)Decimal()的参数是字符串,如果不注意这一点,把浮点数作为参数传递进来,得到的结果还是不精确的
20 >>> Decimal(0.1) + Decimal(0.1) + Decimal(0.1)
21 Decimal('0.3000000000000000166533453694')
22 >>>
23 >>> #(2)计算结果返回的还是Decimal类型,可以用float()函数将其转换为浮点数
24 >>> a = Decimal('7.1') / Decimal('3.1')
25 >>> float(a)
26 2.2903225806451615
27 >>>
28 >>> #如果计算结果应该是整型的,还可以通过int()函数转化为整型
29 >>> b = Decimal('1.0') + Decimal('1.0')
30 >>> int(b)
31 2
32 >>> #如果计算结果应该为浮点型的,通过int()函数转化回事什么结果呢
33 >>> c = Decimal('1.0') + Decimal('1.1')
34 >>> int(c)
35 2
36 >>>
37 >>> d = Decimal('1.5') + Decimal('1.1')
38 >>> int(d)
39 2
40 >>> #看来int()是直接将浮点数的小数部分舍去了
41
42 >>> #(3)浮点数计算中经常会遇到的一个问题,两数向除,但不能相除的情况
43 >>> Decimal('2') / Decimal('3')
44 Decimal('0.6666666666666666666666666667')
45 >>> #小数点后面这么多位,可是要这么多位没什么用
46 >>> #可以事先定义一下Decimal计算的精度
47 >>>
48 >>> from decimal import getcontext
49 >>> getcontext().prec = 4 #设置小数点精度而4
50 >>> Decimal('1.0') / Decimal('3.0')
51 Decimal('0.3333')
52 >>>
拓展三:字符串和元组属于不可变序列,不能通过下标的方式来修改其中的元素值,如代码块1.3.1.5所示:
1 >>> x = (1,2,3)
2 >>> x
3 (1, 2, 3)
4
5 >>> x[1] = 5 #元组是不可变序列,不支持元素值的修改
6 Traceback (most recent call last):
7 File "<pyshell#184>", line 1, in <module>
8 x[1] = 5
9 TypeError: 'tuple' object does not support item assignment
10 >>>
11 >>> y = 'I love China' #字符串是不可变序列,不支持元素值的原位改变
12 >>> y[0] = 'We'
13 Traceback (most recent call last):
14 File "<pyshell#187>", line 1, in <module>
15 y[0] = 'We'
16 TypeError: 'str' object does not support item assignment
17 >>>
代码块1.3.1.5
拓展四:在Python中,允许多个变量值指向同一个值,如代码块1.3.1.6所示
1 >> x = 3
2 >>> id(x) #获取变量 x 在内存中的地址
3 501678608
4 >>>
5 >>> y = x
6 >>> id(y)
7 501678608
代码块1.3.1.6
然而,继续上面的示例代码,当其中一个变量修改值以后,其内存地址将会变化,但着并不影响另一个变量的地址,如代码块1.3.1.7所示
1 >>> x += 6
2 >>> id(x) #这 x 已经不是之前的 x 了
3 501678800
4 >>>
5 >>> y
6 3
7 >>> id(y) #这 y 还是之前的 y
8 501678608
9 >>>
代码块1.3.1.7
在拓展四的代码中,内置函数id()用来返回变量所指的内存地址。可以看出,在Python中修改变量值的操作,并不是直接修改变量的值,而是修改了变量指向的内存地址(引用)。这是因为Python解释器首先读取变量 x 原来的值,然后将其加6,并将结果存放于内存中,最后将变量x指向该结果的内存空间。
Python采用的是基于值的内存管理方式,如果为不同变量赋值为相同值,这个值在内存中只有一份,多个变量指向同一块内存地址,前面的几段代码也说明了这个特点。如代码块1.3.1.8所示
1 >>> l = [1,1,1]
2 >>> id(l[0]) == id(l[1]) == id(l[2])
3 True
4 >>>
5 >>> #可见,列表l的三个元素的内存地址都是相同的
代码块1.3.1.8
当一个变量不再使用时,可以使用 del 命令将其删除。Python具有自动内存管理功能,类似于Java的内存垃圾回收机制,对于没有任何变量指向的值,Python自动将其从内存中删除,至于什么时候删,由程序决定。Python会自动跟踪所有值,并自动删除没有变量指向的内存中的值。
最后,在定义变量名的时候,需要注意以下几个问题:
(1)变量名必须以字母或下划线开头,但下划线开头的变量有特殊含义,这部分在第四章介绍。
(2)变量名中不能有空格或标点符号(括号、引号、逗号、斜线、反斜线、冒号、句号、问号)。
(3)不能使用关键字作为变量名,可以导入keyword模块后使用print(keyword.kwlist)查看所有关键字,需要注意,随着Python版本的变化,关键字列表可能也会有变化,如代码块1.3.1.9所示
1 >>> import keyword 2 >>> print(keyword.kwlist) 3 ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally',
'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'] 4 >>> 5 >>> #或者还有更简单的方法,直接判断自定义的变量名是不是关键字 6 >>> xyz = 0 7 >>> keyword.iskeyword(xyz) 8 False 9 10 #说明变量名xyz不是关键字
代码块1.3.1.9
(4)不建议使用系统内置的模块名、类型名或函数名以及导入的模块名及其成员名作为变量名,这会改变其类型的含义,甚至会导致其他代码无法正常执行。可以通过dir(__builtins__)查看所有内置对象名称。
(5)Python变量名对英文字母大小写敏感,如student 和 Student 是不同的变量。
拓展五:Python变量不直接存储值,而是存储对象的引用,正是这个特定使得Python变量类型可以动态改变,随时可以指向另外一个完全不同类型的对象。为变量赋值时,首先在内存中寻找一块合适的区域把值存放于其中,然后把这个内存地址赋值给变量。
拓展六:Python字符串对象提供了一个方法isidentifier()可以用来判断指定字符串是否可以作为变量名、函数名、类名等标识符。如代码块1.3.1.10所示
1 >>> 'abc'.isidentifier()
2 True
3 >>>
4 >>> '3abc'.isidentifier()
5 False
6 >>>
7 >>> '_3abc'.isidentifier()
8 True
9 >>> '__3abc'.isidentifier()
10 True
11 >>> ',__3abc'.isidentifier()
12 False
13 >>> 'a,bc'.isidentifier()
14 False
15 >>>
代码块1.3.1.10