1、Python program structures.
(1) Programs are composed of modules.
(2) Modules contain statements.
(3) Statements contain expressions.
(4) Expressions create and process objects.
2、Python built-in Types:
如图所示,List是指没有重复元素的collection;Dictionary是指key-value这样存储的集合;Tuple应该就是collection吧,这个不是很清楚,后面会详细讲;本章重点讲述的是Number。
3、Numbers,首先看一张图,这是Python支持的Number列表:
由上图可以看到,Python首先支持integer,这里需要注意的是Python中的integer就相当于C中的long,也就是说,数据宽度至少 是32Bit;第二,Python支持没有限制的Long integers,这种integer在书写的时候要在后面加上一个 L 或 l 来表示这是一个long型的integer,如果没有加的话也不要紧,因为如果Python在计算的时候发现溢出了(overflow),她就会自动将溢 出的integer声明成Long型的,然后继续,所以,不加也无所谓(Attention:在Python 2.2之前的版本中,必须加 L 或 l,换句话说,2.2之前的Python不会在overflow的时候自动将integer变成long);第三,Python支持Float,她的 float就相当于C中的double了;第四,Python还支持八进制和十六进制表示法,这和C一样(八进制以0打头,十六进制以 0x 或 0X 打头);最后,Python还支持复数,这是C没有的。
4、Python支持的Expression,注意,这个表中列的不光是针对Number的Expression,基本上Python所支持的expression都在这里了(包括逻辑运算):
图上可以看到,大部分的operator都可以理解,有些没见过的将在将来讲述。
5、书中还讲述了什么operator优先级、括号的作用以及类型强制转换规则等,这些都学过,不赘述了。
6、Python也支持operator overload,比如 + ,操作两个Number的时候就是做加法,操作两个string的时候就是做字符串连接,当然,我们也可以自己写代码重载operator,实现自己的逻辑。
7、举例。Python中的变量不需要声明,直接赋值即可,以 # 开头的都是注释,如:
% python
>>> a = 3 # Name created
>>> b = 4
这些操作鬼都看的明白:
>>> a + 1, a - 1 # Addition (3+1), subtraction (3-1)
(4, 2)
>>> b * 3, b / 2 # Multiplication (4*3), division (4/2)
(12, 2)
>>> a % 2, b ** 2 # Modulus (remainder), power
(1, 16)
>>> 2 + 4.0, 2.0 ** b # Mixed-type conversions
(6.0, 16.0)
这个例子就有点意思了:
>>> b / (2.0 + a) # Auto echo output: more digits
0.80000000000000004
>>> print b / (2.0 + a) # print rounds off digits.
0.8
这里可以看到,print有规整化输出的功用。
关于格式化输出的例子,这里还有:
>>> num = 1 / 3.0
>>> num # Echoes
0.33333333333333331
>>> print num # Print rounds
0.333333333333
>>> "%e" % num # String formatting
'3.333333e-001'
>>> "%2.2f" % num # String formatting
'0.33'
这里最后用到的就是格式化字符串的方法了,看到了吧,用法就是 "格式化字符串" % "变量",这样,变量的输出就被格式化了。
8、除法。Python的除法有点意思,分为 / 和 // 两个操作符。/ 符号如果不做特殊处理,那么,他会根据操作数的类型给出结果,比如,一个整数 / 一个整数,那么,就算除下来有小数,/ 符号也会将其截断,因为 / 认为结果也要是integer;如果是 float / float,那么,结果就有小数,也是float。相比而言,// 就是纯纯正正的除法取整了,也就是说,不管操作数是什么类型,采用 // 操作符,出来的结果肯定是取整后的整数。在Python的书中,把 / 操作符称为classic division,把 // 称为Floor division。此外,书中还提到了True division,这是什么意思呢?这就是纯正的除法了,也就是说,不管操作数是什么类型,除下来结果该是多少就是多少,不做任何处理,比如两个整数相 除,除下来结果是整的就是整的,是有小数的就是有小数的,这就是True division。书中说了,在将来的Python 3.0里面,/ 符号就要变成 True division 而不是classic division,而 // 不变;在目前版本的Python中,其实已经支持True division,只不过要做一下声明:>>> from __future__ import division,做了这个声明后,再使用 / 操作符就是做True division了,不做这个声明用 / 操作符,就是做classic division。
9、有关bit操作和long操作就不讲了,简单。
10、八进制、十进制和十六进制。八进制以0开头,十六进制以 0x 或 0X 开头。用oct、hex这两个built-in的函数可以将十进制变成八进制和十六进制,如下:
>>> oct(64), hex(64), hex(255)
('0100', '0x40', '0xff')
int函数可以将一个字符串变成一个整数,这个函数有第二个参数,就可以指定将字符串变成何种进制的数,如:
>>> int('0100'), int('0100', , int('0x40', 16)
(100, 64, 64)
eval函数和BASH中的eval一样,可以将参数做为一句Python的代码并加以执行,如:
>>> eval('100'), eval('0100'), eval('0x40')
(100, 64, 64)
最后,我们可以使用字符串的格式化功能来将不同进制的数字格式化成字符串,如:
>>> "%o %x %X" % (64, 64, 255)
'100 40 FF'
11、Python中还有一些包可以用数字方面的运算,如math包:
>>> import math
>>> math.pi, math.e
(3.1415926535897931, 2.7182818284590451)
>>> math.sin(2 * math.pi / 180)
0.034899496702500969
>>> abs(-42), 2**4, pow(2, 4)
(42, 16, 16)
>>> int(2.567), round(2.567), round(2.567, 2)
(2, 3.0, 2.5699999999999998)
这里看到,abs和pow不是math包中的函数,而是标准built-in的函数,最后的round(2.567, 2)指保留两位小数,如果用print round(2.567, 2)的话,就会输出2.57了。
12、有一些Python的扩展包可以做更高级的数字运算,比如NumPy module,她就可以做矩阵运算等等,NumPy module不在Python中,需要独立下载和安装。
13、本章的最后一节解释了Python的一些原理。为什么Python中的变量不需要声明?名字不需要声明,甚至类型都无需声明。这是因为Python将任何变量都看成是对一个object的引用,变量的具体类型要等到执行的时候才会被确定,这就是原因。
14、这里是针对上面一些话的解释。比如,考虑 a = 3 这个expression,在Python内部,a是这样被定义的(图一):
看到了么?a只是一个name,Python会分配一块内存,用来存储3,然后将a定义为指向3的一个引用。我们可以把这里的引用想象成C中的 void * ,所以,a不需要类型,3也不需要类型,只是一个object,然后a指向3,仅此而已。
15、需要注意的是,Python为了节省内存,会做一个share object name的动作,就是将值一样的变量都指向一个object,比如考虑这样的代码:
>>> a = 3
>>> b = a
在Python中,是酱紫的(图2):
看到了么?a和b指向一个object,如果:
>>> a = 3
>>> b = a
>>> a = 'spam'
那么,就会变成酱紫(图3):
16、上面的情况是没有问题的,这是因为a和b两个变量指向的object本身是不可改变的(是常量),在Python中称这类object是 immutable的,但是,如果变量指向的object是mutable的,那么,Python的这种share object name的行为就要当心了,比如:
>>> L1 = [2,3,4]
>>> L2 = L1
如果此时,这样做:
>>> L1 = 24
没问题,因为L1重新指向一个object了,L2还是一个2, 3, 4的List,但是,如果这样:
>>> L1[0] = 24
>>> L2
[24, 3, 4]
看到了么?L2也发生变化了,这是因为List本身是mutable的,是可以被修改的,由于L1和L2指向同一个object,所以,L1修改了object,从L2中读出来的object也变化了。
17、我们会在后面的章节中讲到如何关闭Python的这种变量共享object的特性,从而来避免上述的问题,也就是说,就算object一 样,Python 也会为每个变量都分配这样的object,这些变量都指向不同的object,这样上述问题就完全避免了,但是浪费内存了。
18、Garbage collection。一开始我就说了,这个Python简直和JAVA一模一样!看看吧,这个garbage collection也和java一样,反正就是哪个object没有人reference了,就会被PVM释放呗,比如:
>>> x = 42
>>> x = 'shrubbery' # Reclaim 42 now (?)
>>> x = 3.1415 # Reclaim 'shrubbery' now (?)
>>> x = [1,2,3] # Reclaim 3.1415 now (?)