一、编码规则
1.代码缩进。
Python中代码缩进是一种语法,并以此区分代码的分块和区分代码参差关系。
2.分隔符。
Python中一般通过换行来识别语句的结束,也可在每条末尾加分号来标识,如:
a=5
b=6;
c=7
或 a=5;b=6;c=7
3.续行符。
如果语句太长,可以使用续行符“/”将多行进行连接。
二、内置对象类型
1.数字。
包含4中类型的数:整形;长整形;浮点型;复数型
2.字符串
1).转义符“\”。
字符型数据一般用单引号或双引号包络,且必须成对出现。如字符串内部有单双引号,则需通过转义符实现,例如:
str='what\'s up with you?'
2).格式化表达。
使用%运算符来格式化字符串。在字符串内部,%s表示用字符串替换,%d表示用整数替换,%f表示浮点数替换,有几个%占位符,后面就跟几个变量或者值,顺序要对应好。如果只有一个%,括号可以省略。如:
>>> 'Hello, %s' %'world'
'Hello, world'
>>>'Hi, %s, you have $%d.' % ('Michael',1000000)
'Hi, Michael, you have $1000000.'
2).三重引号。
Python中有一种特殊的三重引号内的字符串格式,被称作“块字符串”,这是一种编写多行文本数据很便捷的语法,例如:
>>> str='''abc
... def
... ghi
... xyz'''
>>> str 'abc\ndef\nghi\nxyz'
除此之外,还可以通过三重引号来废除多行代码,使其无效,而不用逐行行首添加#。需要再次使用该部分代码是秩序去掉首尾的三重引号即可。例如:
'''以下几行代码的主要作用是创建菜单栏并在菜单栏添加子菜单'''
menu =AFXMenuPane(self)
AFXMenuTitle(self, '主菜单', None,menu)
AFXMenuCommand(self, menu, '子菜单一',
afxCreatePNGIcon(r"icon\icon1.PNG"),
myForm1(self),AFXMode.ID_ACTIVATE)
AFXMenuCommand(self, menu,'子菜单二',
afxCreatePNGIcon(r"icon\icon2.PNG"),
myForm2(self),AFXMode.ID_ACTIVATE)
'''
subMenu =AFXMenuPane(self)
AFXMenuCascade(self, menu, '子菜单三', None,subMenu)
AFXMenuCommand(self, subMenu, '子项目1',None,
self,AFXMode.ID_ACTIVATE)
AFXMenuCommand(self, subMenu, '子项目2',None,
self,AFXMode.ID_ACTIVATE)
'''
3.元组(tuple)
元组型数据(tuple)由一系列元素组成,且对每个元素的数据类型不做限制,可以使用字符串、整型、浮点型的混合。元组在建立时,以小括号包括逗号(,)进行间隔,并且可以是多维数据。元组中的元素一旦确定就不允许修改。如:
>>> pets=(("dog",2),("cat",3),("hamster",5)) #创建多维元组
>>> len(pets)
3 #其长度是按照第一维数据计算
>>> pets[2][0] #调用元组中的某一个数据
'hamster'
4.列表(list)
列表型数据(list)指的是能够存储有序元组的数据结构,在Python语言中,列表中的所有元素都包括在方括号[,]内,各元素之间使用逗号分割。与元组不同的是,用户可以对列表中的元素进行添加、删除、修改等操作,因此,列表是可操作的数据结构。
>>> myList =[0,1,2,1,2,3,2,3,4,3,4,5]
>>> myList.count(2) #返回某一元素在list中出现的次数
3
>>> myList.index(5) #返回某一元素在list中首次出现的索引号
11
>>> myList.index(4) #当某一元素多次出现时,返回其首次出现时的索引号
8
>>> myList.insert(2,22) #在列表中指定位置插入元素
>>> myList
[0,1, 22, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5]
>>> myList.sort() #对列表中元素进行排序
>>> myList
[0,1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 22]
>>> myList
[1,9, 3]
>>> myList.append(33) #在列表末尾添加新元素
>>> myList
[1,9, 3, 33]
>>> myList.remove(9) #移除列表中的元素
>>> myList
[1,3, 33]
5.字典(dictionaries)
字典型数据(dictionaries)是Python之中最灵活的内置数据结构类型,列表是有序的对象集合,而字典是无序的集合。两者的主要区别在于,在字典中元素是通过键来存取的,而不是通过顺序索引号来存取,字典中的元素没有特定的顺序。
字典型数据用大括号{ ,}包络,字典中的每一组元素都包含数据键key和数值value两部分,两者之间以冒号间隔,冒号前面是键key,后面是数值value。key是独一无二的,且不可改变,可以是字符串型、整型、浮点型或者元组等多种类型。字典中的两个元素之间用逗号隔开。当需要访问字典中的某一元素时,需要通过索引数据键来获取其对应的数据值。定义方式如下:
>>> insects={"AAA":5000,"BBB":200,"CCC":1200} #定义包含3个元素的字典
>>> insects["AAA"] #获取键"AAA"所对应的值
5000
或
>>> insects=dict(AAA=5000,BBB=200,CCC=1200)
>>> insects
{'AAA': 5000, 'BBB': 200, 'CCC': 1200}
6.集合(set)
集合(set)又分为普通set和frozenset两类,都是无序的,都不属于sequence类型。set类型数据是可以改变的,可以增加、删除元素。frozenset是不可变的,frozenset可以作为字典的键。
set中的数据都是独一无二的,如果某一set中已经含有了某数据,则使用add( )函数时,不会再增添一个。
>>> set_fox=set(("AA","BB","CC")) #定义普通set
>>> set_fox=frozenset(("AA","BB","CC")) #定义frozenset
>>> "AA" in set_fox #判断set中是否包含某一项
True
7.布尔型
Python的布尔类型扩展了Python中真假的概念,布尔类型有True或者False两个变量值,一般Python中判断语句的判断结果不使用1和0来表征判断结果的真假,而是采用布尔型的True或者False来表征。
Python提供了一个内置的bool函数,它可以测试一个对象的布尔值,当一个对象为0或者空值时,测试结果为False;当对象为非零或非空时,测试结果为True。
>>> bool([]) #空值
False
>>> bool(['']) #含空字符串的非空列表
True
>>> bool(1) #非零
True
>>> bool(0) #零值
False
8.None型
Python还有一个特殊对象:None。一般起到一个空的占位作用,类似于C语言中的NULL。None是一个真正的对象,并且真用内存空间。一般对于一个自定义函数,当不使用return指定其返回值时,默认地会返回None。另外,也可以通过None占用内存实现对可变对象的预分配。
>>> X=[None]*999
>>> X
[None, None,None, None,…, None,None]
9. 数据格式转换
1)将字符串类型转化为列表类型
>>> myString='noise'
>>> myList = list(myString)
>>> myList
['n', 'o', 'i', 's', 'e']
>>> myList[0] = 'p' #将列表中第一元素重新赋值。
>>> myList
['p', 'o', 'i', 's', 'e']
2)将字符串类型转化为元组类型
>>> myTuple = tuple(myString)
>>> myTuple
('n', 'o', 'i', 's', 'e')
3)将元组转化为列表
>>> mylist=list(myTuple)
>>> mylist
['n', 'o', 'i', 's', 'e']
4)将浮点型转化为整型
>>> a=3.1415
>>> b=int(a)
>>> b
3
5)将整型转化为浮点型
>>> c=float(b)
>>> c
3.0
6)将浮点型数据转化为字符串
>>> c=3.0
>>> str(c)
'3.0'
10. 对象查询与索引
读者可以使用type()函数来查询某对象的数据类型,也可以通过min()和max()函数查询元组或者列表中数据的最小值或最大值。另外还可以通过index()函数查询某个索引号对应的元素值等,下面将简单介绍几种常用的对象操作函数。
三、动态类型
在Python语言中使用变量时,都没有声明变量的存在以及类型,但变量还可以工作。这一点与静态编译语言C、C++或Java有很大的区别。这就是Python语言的动态类型模型。在Python语言中,数据类型是在运行过程中自动决定的,而不是通过代码声明。变量在赋值的时候才被创建,它可以引用任何类型的对象,变量和对象分别存储在内存中的不同位置,两者通过链接进行关联。
对于下列代码:
>>> a=5
Python将会执行3个不同的步骤去完成这个请求,这些步骤反映了Python语言中所有赋值的操作过程。
(1)创建一个新对象来代表数字5。
(2)创建一个变量a。
(3)将变量a与新对象a相关联。
在Python中从变量到对象的链接称作引用。也就是说,引用是一种关系,以内存中的指针形式实现。一旦变量被使用(也就是被引用),Python自动跟随这个变量到对象的链接。
1.类型的归属
在Python语言中,类型属于对象,不属于变量,我们可以对一个变量进行多次赋值,且允许每次赋值的类型不同。变量名根本没有类型。实际上Python的变量就是在特定的时间引用了一个特定的对象,而对象是具有类型的,每个对象都包含了一个头部信息,其中标记了对象的类型。
2.垃圾回收机制
在Python中,每当一个变量名被赋予了一个新的对象时,且之前的那个对象没有被其他变量名或对象所引用的话,那么之前的那个对象占用的空间就会被回收,这种自动回收对象占用空间的技术叫作垃圾回收。
在Python内部,垃圾回收是如何实现的呢?实际上,每个对象中都保持了一个计数器,计数器记录了当前指向该对象的引用次数,也就是该对象被引用的次数。一旦这个计数器被设置为零,这个对象的内存空间就会被自动回收。垃圾回收最直接且可感受的好处就是,可以在脚本中任意使用该对象而不需要考虑释放内存空间。与C和C++这样的底层语言相比,省去了大量基础代码。
3.共享引用&原处修改
首先看一个两个变量的重复赋值实例。
>>> a=5
>>> b=a
>>> a,b
(5,5)
该实例中,第一行创建了对象5,并将变量a与之关联,第二行创建了变量b,变量b也成为对象5的一个引用。实际上,变量a和变量b都引用了相同的对象,都指向了相同的内存空间,这在Python语言中叫作共享引用——多个变量名引用同一对象。对上述代码做如下修改:
>>> a=5
>>> b=a
>>> a ='five'
>>> a,b
('five',5)
第三行代码创建了一个新的对象'five',并设置a对这个新的对象进行引用,而b仍然继续引用之前的对象5。
与其他语言不同,在Python中,给一个变量赋一个新的值,并不是替换了原始的对象,而是重新创建一个不同的对象,并让这个变量去引用这个新的对象。实际效果就是,对一个变量赋值,仅仅会影响被赋值的变量。但是,也有一些特殊的情况,当引用一些可变对象时,在原处对对象进行修改时,就会出现不一样的情况。例如,在一个列表中对某一个偏移位置进行重新赋值时,会改变这个列表对象,而不是生成一个新的对象。首先看一个容易理解的实例:
>>> a=[1,2,3]
>>> b=a
>>> a
[1, 2,3]
>>> b
[1, 2,3]
>>> a=999
>>> a
999
>>> b
[1, 2,3]
由程序执行结果可以看出,上述实例中一开始变量a和b都引用了列表对象[1,2,3],后来当对a重新赋值后,创建了新的对象999,并让a引用了这个新的对象,整个过程中b并没有发生变化,这与前面的实例类似,同属于共享引用的范畴。然而,列表中的元素都是通过其索引位置进行读取的,例如:
>>> a=[1,2,3]
>>> b=a
>>> a[0],a[1],a[2]
(1, 2,3)
其中,a[0]引用的是对象1,a[1]引用的是对象2,a[2]引用的是对象3。当然,列表自身也是一个对象,接下来对上述代码做一下简单的修改,就会出现明显不同的结果。
>>> a=[1,2,3] #创建列表对象[1,2,3]和变量a,并让a引用该对象
>>> b=a #创建变量b,并让b引用同一列表对象
>>> a
[1, 2,3]
>>> b
[1, 2,3] #变量a和b数值相同
>>> a[0]='one' #修改变量所引用的对象的一个元素
>>> a
['one', 2,3] #变量a数值发生变化
>>> b
['one', 2,3] #变量b数值也发生变化
在上述程序中,我们没有改变a,只是改变了a所引用对象的一个元素,这类修改会覆盖列表对象中的某些部分,它不仅仅会影响变量a,也会同时影响变量b,因为它们引用的是同一个列表对象。对于这种在原处修改的对象,共享引用时需要加倍小心,不注意的话非常容易出错。
如果不希望上述情况出现时,需要使用Python的对象复制,而不是创建引用。Python有多种复制列表的方法,现列举如下。
【实例】列表对象复制
>>> a=[1,2,3]
>>> b=a[:] #复制列表
>>> a
[1, 2,3]
>>> b
[1, 2,3]
>>> a[0]=999
>>> a
[999, 2,3]
>>> b
[1, 2,3] #a引用的列表中某一元素变化时,b未改变。
这种情况下,对a的修改不会影响b,因为b引用的是a所引用对象的复制,两个变量指向了不同的内存区域。需要注意的是,这种分片技术不能用于集合和字典等非序列类型的对象中。
除了上述复制方法之外,还可以使用copy( )函数实现,例如:
【实例】copy()函数
>>> import copy
>>> a=[1,2,3]
>>> b=copy.copy(a)
>>> b
[1, 2,3]
>>> a[0]=999
>>> a
[999, 2,3]
>>> b
[1, 2,3]
另外,需要注意的是,copy()函数可以用于集合或者字典等无序的对象类型中。
四、运算符
1.算数运算符
注: 在Python中加法运算不仅限于数据类型,还适用于字符串、列表等类型
2.关系运算符
3.逻辑运算符
4.运算符优先级
五、结构化程序设计
1.if条件语句
if语句的表达形式如下。
if :
elif :
else:
实际上,elif和else部分可以省略,并且每一段代码块中可以嵌套一个以上的语句。需要注意的是,if、elif以及else必须垂直对齐,具有相同的缩进位置。
2.while循环
while循环语句是Python语言中最通用的迭代结构,只要while语句的顶端测试一直是真值,那么就会一直执行循环体内的代码块,每次循环之后,控制权会返回到开头部分,直到测试为假时,控制权才会传给while块之后的语句。while循环的一般格式如下:
while:
else:
其中,while和else的缩进位置必须一致。需要注意的是,Python中没有其他语言所谓的“dountil”的概念,不过程序员可以在循环主体内部添加一个测试语句和break/continue/pass语句来实现类似的功能。其格式如下。
while:
if :break
if :continue
if :pass
else:
其中,break代表的是跳出最内层循环,执行之后会立刻离开循环;continue代表的是跳过本次循环,直接跳至下一次循环;pass语句是无运算的占位语句,它通常用于为复合语句编写一个空的主体。
3.for循环
for循环在Python中是一个通用的序列迭代器,可以遍历任何有序的序列对象中的元素。for语句可用于字符串、元组以及列表等多种数据类型。for循环的一般格式如下。
for in:
else:
当运行for循环时,Python会逐个将序列对象中的元素赋值给目标,然后为每个元素执行循环主体。for循环也支持一个选用的else块,如果循环结束时没有碰到break语句,就会执行else语句,前面介绍的break和continue语句同样可以用于for循环,例如:
for in:
if :break
if :continue
else:
六、函数
1.函数的定义
定义函数时需要使用关键字def,后面紧跟函数名和一对圆括号,结尾处为冒号,圆括号内部是参数名。函数的声明格式如下。
def ():
【实例】定义函数
>>> def add(x,y):
... add=x+y
... print 'the sum of x and y is %f.' %add
>>> add(1,2)
the sum of x and y is 3.000000.
2.形参与实参
在函数初始调用时,圆括号中的参数称为形参,当调用所定义的函数时,圆括号内给定的具体参数值为实参。在上例中,x和y即为形参,1和2则为实参。形参与实参必须一一对应,参数的类型和顺序也要一致。只有在为形参提供了默认参数值的情况下,顺序才可以打乱。以下是给定形参默认值的示例:
>>> def add(x=4,y=5):
... add=x+y
... print 'the sum of x and y is %f.' %add
... print 'x is %f.' %x
...
>>> add(1,2)
the sum of x and y is 3.000000.
x is 1.000000.
>>> add(x=10,y=20)
the sum of x and y is 30.000000.
x is 10.000000.
>>> add(y=20,x=10)
the sum of x and y is 30.000000.
x is 10.000000.
七、模块
一般来说,当退出Python编译器之后再次重新进入时,之前创建的一切变量或者函数就全部丢失了。如果希望长时间地保存程序,方便随时调用,就需要用到模块的概念。
模块一般是以.py为后缀的文件,文件包括函数定义和声明,文件名即为模块名。例如将下列代码存储到一个名为Add.py的文件中即创建了一个名为Add的模块。
1.模块调用
模块导入有以下几种格式。
(1)import module_name:导入整个模块。
(2)from module_name import function_name:从模块中导入某个函数类。
(3)from module_name import *:导入模块中的所有函数和类。
(4)from module_name import function_name asshort_name:导入模块中的某个函数,并用简写的函数名short_name替代原函数名function_name,一般适用于函数名较长的情况。
第一种模块导入方式和后面几种导入方式的区别是,当使用第一种模块导入方法并调用其内部函数时,函数名之前必须使用模块名module_name作为前缀,即module_name.function_name();当使用后面几种模块导入方法时,函数可以直接调用,不需要使用模块名作为前缀。
【实例】模块的调用
>>> from Add import add
>>> add(4,5)
the sum of x and y is 9.000000.
x is 4.000000.
>>> from Add import *
>>> add(4,5)
the sum of x and y is 9.000000.
x is 4.000000
>>> from Add import add as A
>>> A
>>> A(4,8)
the sum of x and y is 12.000000.
x is 4.000000.
八、包导入
除了导入一个模块名之外,Python还可以导入指定的目录路径,Python代码的目录就称为包,这类对目录的导入就称为包导入。实际上,包导入是把计算机上的目录变成另一个Python的命名空间,而属性则对应目录中所包含的子目录和模块文件。
包导入对于组织大型系统内的文件会很方便,而且可以简化模块搜索路径的设置。包导入的语法与模块导入类似,区别在于包导入时需要指定文件的路径。
import dir1.dir2.module_name
from dir1.dir2.module_name importfunction_name
上述语句中的“点号”路径与计算机上的目录路径一致,dir1为一级目录,dir2为dir1中的二级子目录,dir2中包含了一个名为module_name.py的模块文件,同样,该模块文件中定义了名为function_name的函数。
需要注意的是,在使用包导入时,包导入语句所提及路径中的每个目录内都必须有一个init.py文件,否则导入包会失败。init.py文件的作用是将当前文件夹标记为一个包,相当于包的注册文件,init.py的内容可以为空。
1.包、模块、函数之间的关系
读者可以将常用的代码合并到一个包中,通过调用该包内的各个模块来实现代码的重用。下图为包、模块和函数三者之间的关系图,每个包内可以包含多个子包或模块,且每一级包内都必须包含init.py文件,另外,每个模块文件内可以定义多个函数。
2. 包的定义和调用
按照上图所示的组织结构图,在Abaqus的工作目录下,例如D:\Temp文件夹内创建一个名为package的文件夹,该文件内创建两个子文件夹(subpackage1和subpackage2)和一个init.py文件,subpackage1内创建一个模块文件module1.py和一个init.py文件,module1.py源代码如下。
def add(x,y):
add=x+y
print 'the sum of x and y is %f.' % add
然后在subpackage2内创建一个子包subpackage3、一个模块文件module2.py和一个init.py文件,同样,在subpackage3内创建一个模块文件module3.py和一个init.py文件,module3.py源代码如下。
def multiple(x,y):
m=x*y
print 'the product of x and y is %f.' % m
return m
上述定义完成后,在Abaqus GUI命令交互行输入以下指令并查看计算结果。
>>> from package.subpackage1.module1 importadd
>>> from package.subpackage2.subpackage3.module3 importmultiple
>>> add(4,5)
the sum of x and y is 9.000000.
>>> multiple(4,5)
the product of x and y is 20.000000.
20
如果将subpackage1中的init.py文件删除,然后重新执行包导入指令,则会出现以下提示错误。
>>> from package.subpackage1.module1 importadd
ImportError: No module named subpackage1.module1
提示:
在Abaqus GUI图形界面开发过程中,将大量运用包导入,尤其是自定义GUI应用程序的开发过程中(详见本书第六章内容),使用包导入可以轻松地找到对应文件,简化文件搜索路径设置,使复杂程序的组织结构更加清晰,提高代码的可读性,同时也便于对代码进行管理。本节仅简要介绍了包导入的概念和使用方法,更多关于包导入的知识请参照其他Python语言书籍。
九、文件的操作
1.文件的创建
创建文件需要用到file()函数,该函数的简单声明方式如下:
file(filename,mode)
其中
filename为文件名(可包含路径),mode为文件的打开方式,以下为创建文件的几个实例。
>>> f=file('num.py','w')
>>> f=file("C:\data.py","w")
另外,也可以通过open()函数创建或者打开文件,open()函数声明方式与file()函数类似,以下是采用open()创建和打开本地文件的实例。
>>> f=open('num.py','w')
>>> f=open('num.py','w+')
>>> f=open("C:\data215.py","a")
使用上述两个函数创建或者打开文件时,一定要注意指定文件的打开方式,Python支持只读、写入、读写等多种文件打开方式,具体参照下表:
2.文件的读写
对于一个已创建的文件,经常需要对其进行读写操作。在Python语言中对文件读取和写入的函数分别为read( )、readline()和write(),对于一次读写多行信息时,还可以调用readlines()函数和writelines()函数,具体使用方法参见以下实例。
【实例】文件的写入
编写以下脚本,脚本命名为write.py,本实例脚本存放于随书配套资源\chapter2\2.12中,代码及注释如下。
#! /user/bin/Python
# -*- coding:UTF-8 -*-
f=file('num.py','w') #在工作目录下创建一个名为num.py的文件
f.write("x=%6i\n" %100) #将字符串写入文件num.py
f.write("y=99\n") #将字符串写入文件num.py
for i in range(1,101):
f.write('%i\t' %i)
if i==0:
f.write('\n') #将整数按行列打印
f.close() #关闭文件
上述脚本执行后,在Python工作目录下会创建一个名为num.py的文件,其内容如下。
x=100
y=99
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100