从C/C++到Python(之二)(By Robinvane Suen)

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的逗号表达式不同!
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没有charbool类型,前者用string代替,后者的代替品稍后解释。另外,Python语言增加了复数这样一个数据类型
3.1. 数字
Python的数字类型与C的区别主要在:
1)         整数(int)是用Clong实现的(至少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..
2)         内置两个函数pow和abs。它们也与C语言的math库保持一致。但注意的是它们都可以对复数进行运算。比如abs(3+4j) = 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序列成员关系测试),返回truefalse
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也不同(但JavaC#的字符串比较类似):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.’,它允许在‘ 内部使用双引号“。
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的格式化字符串是一个操作符,它返回一个字符串!
2.         加法+。连接两个字符串,并且返回新的字符串,比如s1 + s2
3.         乘法 * 。重复字符串,并且返回新的字符串,比如若str1 = ‘abc’,则str * 3 = ‘abcabcabc’。
4.         索引[i]。得到从0开始的下标上的位置的字符,比如若str = ‘abc’则str[0] = ‘a’。
5.         分片[i, j]得到下标从ij,包括i,不包括j的子串。比如若str = ‘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]是一个列表)。所以,在介绍列表和元组这两种数据类型的时候就不再介绍上述这几种操作,除非有特殊情况。
索引和分片
Python中,对序列(再说一遍,序列包括字符串、列表和元组)的索引值可以是所有整数(负数、0和正数)。0和正数的索引意义与C中的索引意义一致,对于负数,-1是指序列中最后一个元素,它相当于正数索引len(seq) – 1,更一般地说,若i < 0,则索引值i相当于正数索引len(seq) + i,其中seq是待索引的序列
分片的格式是[start : end],包括start而不包括endstartend与索引的规则一致,可以是所有整数。此外,它们还可以被忽略不写:start被忽略相当于start = 0end被忽略相当于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])其他操作都在原地改变列表(因而速度可能更快)。比如
L1=[1,2,3]
L2=L1[1:]      #L2 = [2,3]
L2[0]=7        #L2 = [7,3], L1 = [1,2,3], L2L1引用的对象不一样,所以L2
                 #改变不导致L1的改变
L3=L2[:]       #L3 = [7,3], 分片返回一个新的与L2内容一样列表对象,相当于深复制
L2=L2+[8]      #L2 = [7,3,8]
L3.applend(8)     #L3 = [7,3,8],有时候+法和append的作用一样,但由于加法生成
#
一个新的对象,并返回其引用,而append直接在原地改变对象,所
#
以通常更快
3.5. 字典
字典提供一种按关键字访问值的数据结构。Python使用Hash而不是树来实现字典,所以它的速度通常较快,但可能占用较大的空间。字典是可变无序集合。字典的写法是用”{“”}”括住:序列,各个:之间使用”,”分割。注意,字典中一个键,只能与一个值关联,否则后添加的值会覆盖之前的值。比如:
D1={}                                  #空列表
D2={‘spam’:2,’eggs’:3,’eggs’:4}   #’eggs’:3会被’eggs’:4所替代
D3={‘spam’:2, ‘eggs’:[3,4]}        #如果一个键需要对应多个值,值可以用列表表示
D2[‘eggs’], d3[‘eggs’][0]          #D2[‘eggs’] = 4, D2[‘eggs’][0] = 3
D2.has_key(‘eggs’)                  #是否含有键’eggs’
D2.keys()                             #返回所有键所组成的列[‘eggs’,spam’]
D2.values()                           #返回所有值所组成的列表[4,2]
len(D1)                                #字典存储的项目的数目
D2[key]=new                           #改变(存在时)或者增加(不存在时)key:new
del D2[key]                            #从字典中删除键key和对应的值
值得注意的是,字典中的键无需是字符串,它可以是任意数据类型以及自定义数据类型。
3.6. 元组
元组的是一个不可变的序列,也就是与string一样,我们无法在原位改变它的值。另外,它是用”(””)”而不是”[””]”括起来的序列。除此之外,其他属性与列表一致。
比如:
1 T0=()                            #空元组
2 T1=(0,)                          #含有一个元素的元组
3 T2=(0,1,2,3)                    #常见的元组形式
4 T2=0,1,2,3                       #允许省略括号,注意与C的逗号表达式不同!
5 T3=(‘abc’, (‘def’, [1,2]))    #允许嵌套
6 T1[0]=0                           #提示错误,不允许变更元组
注意第2行是如何声明一个只有一个元素的元组。为了避免Python(0)看成是一个括号表达式(相当于整数0),我们必须在该元素后面增加一个逗号’,’另外第四行可以看到,元组还有省略括号的写法,注意它与C语言的逗号表达式是不同的!也就是说:
x,y,z=1,2,3
实际上相当于
x = 1
y = 2
z = 3
但是对于C语言语句x,y,z = 1,2,3的效果是z = 1(逗号的优先级比赋值低)!
3.7. 文件
文件对象实际上是C语言的stdio文件系统上的一个包裹,所以文件对象的方法与C标准库中的函数是一一对应的。下面是一些常见操作:

output = open(‘/tmp/spam’, ‘w’)
生成输出文件
input = open(‘data’, ‘r’)
生成输入文件
s = input.read()
把整个文件读到一个字符串中
s = input.read(N)
读N个字节,放到s
s = input.readline()
读下一行
L = input.readlines()
读所有行到一个行列表
output.write(s)
把字符串s写入文件
output.writelines(L)
把列表所有字符串写入文件
output.close()
关闭文件

注意,当遇到文件结尾EOF时,readline()返回””(长度为0的字符串)
另外,Python提供额外的模块提供更高级的文件操作,比如struct模块,它允许我们定义一个记录格式的字符串,然后Python帮我们把文件中的数据按照该记录格式读入变量中。另外还anydbm提供按键访问文件的接口,shelve和pickle模块提供保存整个对象的支持;等等。
3.8. 比较、相等和真值
C/C++不同(甚至与javaC#也不同!)Python的相等测试操作”==”是递归地比较对象地内部对象,如果都相等则返回true,否则返回false!而为了比较两个变量是否引用相同的对象,则需要使用is操作符(这个时候is相当于java中的对象的==操作)。比如:
L1 = [1,2,(3,4)]
L2 = [1,2,(6,7)]
L1 == L2        #返回falseL1L2的内容不同
L2[2] = (3,4)
L1 == L2        #返回trueL1L2的内容相同
L1 is L2        #返回falseL1L2引用不同的对象
另外,由于没有布尔变量,我们需要知道其他变量值的真假值:

“spam”
“”
[]
{}
1
0.0
None
假,相当于C的NULL

 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值