3. 类型与操作符
Python与C/C++不一样,它不是一个强类型的语言。所以,在使用一个变量之前,我们无需声明它的类型 — Python会自动帮我们辨别变量的类型。更重要区别是,变量可以指向任意类型(如果用C#的语言来说,所有变量的类型都是Object,所以它拥有任意指向的能力[java语言没有自动装箱功能,所以有点不一样])。看看下面的例子:
C/C++语言:
double d = 1.2;
int i = ceil(d);
Python语言:
v = 1.2 # v is a double
v = int( math.ceil( v ) ) # ok, and v is now an integer
另外一个值得注意的是在Python中虽然声明一个对象之前无需声明它的类型,但是在使用一个变量之前必须声明以及初始化该变量。比如
i = 1 #声明并初始化变量i
v = i + j #NameError: name ‘j’ is not defined
是错的,Python将提示j没有定义。我们必须:
i, j = 1, 2 #声明和初始化i,j等价于C语句i
= 1, j = 2!它与C的逗号表达式不同!
= 1, j = 2!它与C的逗号表达式不同!
v = i + j #v = 3
3.0. Python的内置数据类型
Python的内置语言类型列表如下:
类型名称
|
常量实例/用法
|
Number(数字), int, long, float, double, complex | 3.2414, 1234, 99999999999999L, 3 + 4j |
String(字符串) | ‘spam’, “guide’s” |
List(列表) | [1,2,3], [1, [1, 2, 3], 5] |
Dictionary(字典) | {‘food’: ‘spam’, ‘taste’: ‘yum’} |
Tuple(元组) | (1, ‘tuple’, 4, ‘U’) |
File(文件) | text = open(‘egg’, ‘r’).read() |
Python的内置数据类型一览表(选自《Python语言入门》,略作修改)
与C/C++相比,Python没有char和bool类型,前者用string代替,后者的代替品稍后解释。另外,Python语言增加了复数这样一个数据类型。
3.1. 数字
Python的数字类型与C的区别主要在:
1) 整数(int)是用C的long实现的(至少32位,与机器字长以及编译Python的C编译器相关)。
2) 长整型(long)与C的long不同,它允许任意长度的整数,写法是数字常量后面加上l或L,比如99999999999999999L。
3) Python有复数类型。复数常量由“实部+虚部”组成,以J或j结束,比如,10+2j。注意,实部和虚部都是用浮点数实现的。
Python对数字的常用操作包括:
1) +,-,*,/。这些于C保持一致。另外增加了操作**,是幂操作,比如2**0.5
= pow(2, 0.5) = 1.414..
= pow(2, 0.5) = 1.414..
2) 内置两个函数pow和abs。它们也与C语言的math库保持一致。但注意的是它们都可以对复数进行运算。比如abs(3+4j) =
5.0(= (32 + 42)1/2)。
5.0(= (32 + 42)1/2)。
3) 工具模块:rand和math。可以使用import rand以及import math使用这两个模块里面的函数。另外,还有Numeric高级库提供矩阵等运算。
3.2. Python表达式操作
Python的某些操作符的写法与C不同,对比列表如下,更详细的说明见3.3 - 3.8小节:
Python
|
例子
|
C
|
x or y | x || y | |
x and y | x && y | |
not x | !x | |
is, is not(身份测试)
|
无 | |
in, not in(序列成员关系测试),返回true或false
|
1 in [1,2] (true);
‘s’ in ‘robin’ (false)
|
无 |
x[i], 索引操作。i可以是任何适当的对象
|
arr = [20,52,13],则arr[0] = 20
dict = {‘k1’: 77, ‘k2’: 98},则dict[‘k1’] = 77
|
x[i],i只能是整数
|
x[i : j],分片操作。i, j是整数,并且可负
|
arr = [20, 52, 13],则arr[1:3] = [52, 13]
|
无 |
(…),元组
|
(21,343,21),21,31,23
|
无 |
[…],列表。可以任意嵌套
|
[21, ‘abc’, 21.0] |
[…],数组。
|
{…},字典。是key:value的集合
|
dict = {‘k1’: 77, ‘k2’: 98} | 无 |
`…`,把对象转换成字符串
|
i = 1;则`i` = ‘1’
|
无 |
Python的表达式操作与C对照的对照表(选自《Python语言入门》,略作修改)
Python中的“序列”至少包括元组、字符串、列表,我们仍然可以重载相应的操作符来生成我们自定义的“序列对象”。操作符x[i]中的x至少可以是序列和字典。x[i : j]中的x至少可以是序列。另外,如果对象重载了上述操作符,则也可以对这些对象施加如上操作符。
3.3. 字符串
Python的字符串相当于C中的字符数组,或者C++的std::string,是一个有序的字符序列。另外,我们之前提到,Python是没有字符(char)类型的!值得注意的是Python的字符串与C的字符数组,甚至与C++的std::string也不同(但与Java和C#的字符串比较类似):Python的字符串是不可变序列。不可变序列的意思是这个对象是不能改变的!举个例子:
对于C++
sd::string str = “robinvane is a good student.”;
str[0] = ‘R’;
std::cout<< str; //str = “Robinvane is a good student.”
但对Python来说:
str = “robinvane is a good student.”
str[0] = ‘R’ #Python提示错误,无法改变对象!
Python的字符串有4种表达方式:
1) 与C一样,用双引号“把字符串包围,例如”robinvane”
2) 用单引号‘把字符串包围,例如’robinvane
is a “good” student.’,它允许在‘ 内部使用双引号“。
is a “good” student.’,它允许在‘ 内部使用双引号“。
3) 用三双引号“““把多行字符串包围。使用三引号包围字符串的时候允许一个字符串跨越多行,并且每行最后自动添加“/n”字符。
4) 原始字符串。以r’’或R’’括住的字符串会忽略字符串内部的转移字符’/’的作用,也就是说’/’依然是’/’,而无需写成’//’,这对书写正则表达式很有用(因为正则表达式经常有字符’/’)。比如r’a/b/c’依然保持它们的反斜线,相当于’a//b//c’。
比如:
str1 = “These apples’ red and big”
str2 = ‘I am so called “good” student’
str3 = “““<table>
/t<tr>
/t/t<td>arb</td>
/t</tr>
</table>””” #str3等价于“<table>/n/t<tr>/n/t/t<td>arb</td>/n/t</tr>/n<table>”
str4 = r’a/b/c’ #相当于’a//b//c’
字符串常用的操作包括:
1. 字符串格式操作。Python格式化字符串操作的格式是:C格式化字符串 % 元组。元组就是用()括起,用”,”分割的对象序列(见3.6)。比如:”a
%s parrot %d” % (‘dead’, 1)返回的值是字符串”a dead parrot 1”。注意,这与C的printf不同,Python的格式化字符串是一个操作符,它返回一个字符串!
%s parrot %d” % (‘dead’, 1)返回的值是字符串”a dead parrot 1”。注意,这与C的printf不同,Python的格式化字符串是一个操作符,它返回一个字符串!
2. 加法+。连接两个字符串,并且返回新的字符串,比如s1 + s2
3. 乘法 * 。重复字符串,并且返回新的字符串,比如若str1 =
‘abc’,则str * 3 = ‘abcabcabc’。
‘abc’,则str * 3 = ‘abcabcabc’。
4. 索引[i]。得到从0开始的下标上的位置的字符,比如若str =
‘abc’则str[0] = ‘a’。
‘abc’则str[0] = ‘a’。
5. 分片[i, j]。得到下标从i到j,包括i,不包括j的子串。比如若str
= ‘abc’,则str[1:2] = ‘b’,str[1:3] = ‘bc’。
= ‘abc’,则str[1:2] = ‘b’,str[1:3] = ‘bc’。
6. 长度len。得到字符串的长度len(‘spam’) = 4
7. 迭代:for x in str:这个语句从左到右遍历字符串str中的每个字符,每次都保存在x中。
8. 测试成员关系:’s’ in ‘robinvane’返回false值。
这里要说明一下的是Python的格式化字符串问题。替代码%s不仅仅可以替代一个字符串,还可以把任意对象转换成字符串!比如为了把一个整数字符串,你可以用”%d”%(1),你也可以用”%s”%(1)!
之前说过,Python内置类型中,属于序列的类型包括字符串(元素是字符)、列表(元素任意)和元组(元素任意),而加法、乘法、索引、分片、长度、迭代和测试成员关系操作对这三种数据类型都适用,而且意义也类似,比如len([1,2,4]
= 3,其中[1,2,4]是一个列表)。所以,在介绍列表和元组这两种数据类型的时候就不再介绍上述这几种操作,除非有特殊情况。
= 3,其中[1,2,4]是一个列表)。所以,在介绍列表和元组这两种数据类型的时候就不再介绍上述这几种操作,除非有特殊情况。
索引和分片
在Python中,对序列(再说一遍,序列包括字符串、列表和元组)的索引值可以是所有整数(负数、0和正数)。0和正数的索引意义与C中的索引意义一致,对于负数,-1是指序列中最后一个元素,它相当于正数索引len(seq)
– 1,更一般地说,若i < 0,则索引值i相当于正数索引len(seq) + i,其中seq是待索引的序列。
– 1,更一般地说,若i < 0,则索引值i相当于正数索引len(seq) + i,其中seq是待索引的序列。
分片的格式是[start : end],包括start而不包括end。start和end与索引的规则一致,可以是所有整数。此外,它们还可以被忽略不写:start被忽略相当于start
= 0,end被忽略相当于end = len(seq)(所谓的最后一个的下一个)。
= 0,end被忽略相当于end = len(seq)(所谓的最后一个的下一个)。
下面是一些例子:
s = ‘spam’
s[0], s[-2] #s[0] = ‘s’, s[-2] = ‘a’
s[1:3], s[1:], s[:-1] # s[1:3] = ‘pa’, s[1:] = ‘pam’, s[:-1] = ‘spa’
3.4. 列表
Python的列表相当于C的数组,或者更像C++ std::vector类型,它是可动态增长的。列表是有序的对象序列。与字符串不同,我们可以在列表中保存任意对象(当然也可以在列表内部再嵌套一个列表,形成所谓的二维列表),并且列表是可变的序列,也就是说我们可以在“原地”改变列表上某个位置所存储的对象(的值)。列表用”[”和”]”括起,各个元素之间使用”,”分割。比如:
L1 = [] #空列表
L2 = [0, 1, 2, 3] #四个整数的列表,索引从0 - 3
L3 = [‘abc’, [‘def’, 1]] #嵌套列表,列表中的元素可以不一样
列表的常用操作(续上表)
L2[i] , L3[i][j], L2[i:j], len(L2),
L1 + L2, L2 * 3
for x in L2
3 in L2
|
索引、分片、长度
合并、重复、
迭代、
成员关系测试(与字符串相应操作的对应)
|
L2.append( -1 ) |
增长。L2 = [0,1, 2,3,-1]
|
L2.sort() |
排序。L2 = [-1,0,1,2,3]
|
L2.index(1) |
查找元素1,返回其下标2
|
L2.reverse() | 反转。L2 = [3,2,1,0,-1] |
Del L2[2]
|
删除索引值2上的元素,缩小列表。L2 = [3,2,0,-1]
|
L2 [1,3] = [] |
删除L2[1:3]分片,L2 = [3, -1]
|
L2 [0] = 1 | 索引赋值,L2=[1,-1] |
L2[: -1] = [4,5,6] |
分片赋值,L2 = [4,5,6,-1]
|
range(4), xrange(0,4) |
生成整数列表,range(4) = [0,1,2,3]
|
注意,如同字符串的+、*、和分片操作一样,列表的这三个操作都返回一个新的列表,而不会改变原列表(除了列表赋值操作L2[:
-1] = [4,5,6])。而其他操作都在原地改变列表(因而速度可能更快)。比如
-1] = [4,5,6])。而其他操作都在原地改变列表(因而速度可能更快)。比如
L1=[1,2,3]
L2=L1[1:] #L2 = [2,3]
L2[0]=7 #L2 = [7,3], L1 = [1,2,3], L2与L1引用的对象不一样,所以L2
#改变不导致L1的改变
L3=L2[:] #L3 = [7,3], 分片返回一个新的与L2内容一样列表对象,相当于深复制
L2=L2+[8] #L2 = [7,3,8]
L3.applend(8) #L3 = [7,3,8],有时候+法和append的作用一样,但由于加法生成
#一个新的对象,并返回其引用,而append直接在原地改变对象,所
#一个新的对象,并返回其引用,而append直接在原地改变对象,所