Python游戏设计案例实战
上QQ阅读APP看书,第一时间看更新

1.2 Python语法基础

1.2.1 Python数据类型

计算机程序不仅可以处理各种数值,还可以处理文本、图形、音频、视频、网页等各种各样的数据。对于不同类型的数据,需要定义不同的数据类型进行处理。

1. 数值类型

Python数值类型用于存储数值。Python支持以下几种数值类型。

• 整型(int):通常被称为是整型或整数,是正或负整数,不带小数点。在Python3里,只有一种整数类型int,没有Python 2.x中的Long。

• 浮点型(float):浮点型数值由整数部分与小数部分组成,浮点型数值也可以使用科学计数法表示(2.78e2就是2.78 × 102 = 278)。

• 复数(complex):复数由实数部分和虚数部分构成,可以用a+bj或者complex(a,b)表示,复数的虚部以字母j或J结尾,例如,2+3j。

数据类型是不允许改变的,这就意味着如果改变数值数据类型的值,将重新分配内存空间。

2. 字符串

字符串是Python中最常用的数据类型。我们可以使用引号来创建字符串。Python不支持字符类型,单字符在Python也是作为一个字符串使用。Python使用单引号和双引号来表示字符串,效果是一样的。

3. 布尔类型

Python支持布尔类型的数据,布尔类型只有True和False两种值,但是布尔类型有以下几种运算。

(1)and(与)运算:只有两个布尔值都为True时,计算结果才为True。

True and True      #结果是 True
True and False     #结果是 False
False and True     #结果是 False
False and False    #结果是 False

(2)or(或)运算:只要有一个布尔值为True,计算结果就为True。

True or True      #结果是 True
True or False     #结果是 True
False or True     #结果是 True
False or False    #结果是 False 

(3)not(非)运算:把True变为False,或者把False变为True:

not True          #结果是 False
not False         #结果是 True

布尔运算在计算机中用来做条件判断,根据计算结果为True或者False,计算机可以自动执行不同的后续代码。

在Python中,布尔类型还可以与其他数据类型做and、or和not运算,这时下面的几种情况会被认为是False:为0的数字,包括0和0.0;空字符串' '和"";表示空值的None;空集合,包括空元组()、空序列[]和空字典{};其他的值都为True。例如:

a = 'python' 
print (a and True)  #结果是 True
b = '' 
print (b or False)  #结果是 False

4. 空值

空值是Python里一个特殊的值,用None表示。它不支持任何运算也没有任何内置函数方法。None和任何其他的数据类型比较之后只会返回False。在Python中未指定返回值的函数会自动返回None。

1.2.2 序列数据结构

数据结构是计算机存储、组织数据的方式。序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字,即它的位置或索引,第一个索引是0,第二个索引是1,以此类推。序列可以进行的操作包括索引、截取(切片)、加、乘、成员检查。此外,Python已经内置确定序列的长度以及确定最大和最小元素的方法。Python内置序列类型最常见的是列表、元组和字符串。另外,Python提供了字典和集合这样的数据结构,它们属于无顺序的数据集合体,不能通过位置索引来访问数据元素。

1. 列表

列表(list)是最常用的Python数据类型,列表的数据项不需要具有相同的类型。列表类似于其他语言的数组,但功能比数组强大得多。

创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可。实例如下:

list1 = ['中国', '美国', 1997, 2000]
list2 = [1, 2, 3, 4, 5 ]
list3 = ["a", "b", "c", "d"]

列表索引从0开始。列表可以进行截取(切片)、组合等。

(1)访问列表中的值

使用下标索引来访问列表中的值,同样也可以使用方括号的形式截取字符,实例如下:

list1 = ['中国', '美国', 1997, 2000] 
list2 = [1, 2, 3, 4, 5, 6, 7 ] 
print ("list1[0]: ", list1[0] ) 
print ("list2[1:5]: ", list2[1:5] )

以上实例输出结果如下:

list1[0]:  中国
list2[1:5]:  [2, 3, 4, 5]

(2)更新列表

可以对列表的数据项进行修改或更新,实例如下:

list = ['中国', 'chemistry', 1997, 2000] 
print ( "Value available at index 2 : ") 
print (list[2] ) 
list[2] = 2001 
print ( "New value available at index 2 : ") 
print (list[2] ) 

以上实例输出结果如下:

Value available at index 2 :
1997
New value available at index 2 :
2001

(3)删除列表元素

方法一:使用del语句来删除列表中的元素,实例如下:

list1 = ['中国', '美国', 1997, 2000] 
print (list1) 
del list1[2] 
print ("After deleting value at index 2 : ") 
print (list1)

以上实例输出结果如下:

['中国', '美国', 1997, 2000]
After deleting value at index 2 :
['中国', '美国', 2000]

方法二:使用remove()方法来删除列表的元素,实例如下:

ist1 = ['中国', '美国', 1997, 2000]
list1.remove(1997)
list1.remove('美国')
print(list1)

以上实例输出结果如下:

['中国', 2000]

方法三:使用pop()方法来删除列表的指定位置的元素,无参数时删除最后一个元素,实例如下:

list1 = ['中国', '美国', 1997, 2000] 
list1.pop(2)                 #删除位置2元素1997 
list1.pop()                  #删除最后一个元素2000 
print (list1)

以上实例输出结果如下:

['中国', '美国']

(4)添加列表元素

可以使用append()方法在列表末尾添加元素,实例如下:

list1 = ['中国', '美国', 1997, 2000] 
list1.append(2003) 
print (list1) 

以上实例输出结果如下:

['中国', '美国', 1997, 2000, 2003]

(5)定义多维列表

可以将多维列表视为列表的嵌套,即多维列表的元素值也是一个列表,只是维度比父列表小1。二维列表(即其他语言的二维数组)的元素值是一维列表,三维列表的元素值是二维列表。例如,定义一个二维列表。

list2 = [["CPU", "内存"], ["硬盘","声卡"]]

二维列表比一维列表多一个索引,可以使用如下方法获取元素:

列表名[索引1][索引2]

例如:定义3行6列的二维列表,打印出元素值。

rows=3 
cols=6 
matrix = [[0 for col in range(cols)] for row in range(rows)]   
#列表生成式生成二维列表
for i in range(rows):   
     for j in range(cols):  
           matrix[i][j]=i*3+j 
           print (matrix[i][j],end=",")   
     print ('\n') 

以上实例输出结果如下:

0,1,2,3,4,5,
3,4,5,6,7,8,
6,7,8,9,10,11,

列表生成式(List Comprehensions)是Python内置的一种功能强大的生成列表的表达式。如果要生成一个list [1, 2, 3, 4, 5, 6, 7, 8,9],则可以用range(1, 10):

>>> L= list(range(1, 10))     #L是[1, 2, 3, 4, 5, 6, 7, 8, 9]

如果要生成[1×1, 2×2, 3×3, …, 10×10],则可以使用如下循环:

>>> L= []   
>>> for x in range(1 , 10):   
         L.append(x*x)   
>>> L   
[1, 4, 9, 16, 25, 36, 49, 64, 81]

列表生成式还可以用以下语句代替以上的烦琐循环来完成:

>>> [x*x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

列表生成式的书写格式:把要生成的元素x×x放到前面,后面设置for循环。这样就可以把list创建出来。for循环后面还可以加上if判断,例如,如下代码可筛选出偶数的平方:

>>> [x*x for x in range(1 , 11) if x%2 == 0]   
[4, 16, 36, 64, 100]

再如,把一个list列表中所有的字符串变成小写形式:

>>> L = ['Hello', 'World', 'IBM', 'Apple'] 
>>> [s.lower() for s in L] 
['hello', 'world', 'ibm', 'apple']

当然,列表生成式也可以使用两层循环,例如,生成'ABC'和'XYZ'中字母的全部组合:

>>> print([m + n for m in 'ABC' for n in 'XYZ'])
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

for循环其实可以同时使用两个甚至多个变量,例如,字典(Dict)的items()可以同时迭代key和value:

>>> d = {'x': 'A', 'y': 'B', 'z': 'C' } #字典
>>> for k, v in d.items():
   print(k, '键=', v, endl=’;’)

程序运行结果:

y 键= B; x 键= A; z 键= C;

因此,列表生成式也可以使用两个变量来生成list列表:

>>> d = {'x': 'A', 'y': 'B', 'z': 'C' } 
>>> [k + '=' + v for k, v in d.items()] 
['y=B', 'x=A', 'z=C'] 

2. 元组

Python的元组(tuple)与列表类似,不同之处在于元组的元素不能修改。元组使用小括号“()”,列表使用方括号“[]”。元组中的元素类型也可以不相同。

(1)创建元组

元组的创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。实例如下:

tup1 = ('中国', '美国', 1997, 2000) 
tup2 = (1, 2, 3, 4, 5 ) 
tup3 = "a", "b", "c", "d"

tup1 =('中国', '美国', 1997, 2000)

如果创建空元组,只需写一个空括号即可。

tup1 =()

当元组中只包含一个元素时,则需要在第一个元素后面添加逗号。

tup1 =(50,)

元组与字符串类似,下标索引从0开始,可以进行截取、组合等。

(2)访问元组

元组可以使用下标索引来访问元组中的值,实例如下:

tup1 = ('中国', '美国', 1997, 2000) 
tup2 = (1, 2, 3, 4, 5, 6, 7 ) 
print ("tup1[0]: ", tup1[0])       #输出元组的第一个元素
print ("tup2[1:5]: ", tup2[1:5])   #切片,输出从第二个元素开始到第五个元素
print (tup2[2:])                   #切片,输出从第三个元素开始的所有元素
print (tup2 * 2)                   #输出元组两次

以上实例输出结果:

tup1[0]:  中国
tup2[1:5]:  (2, 3, 4, 5) 
(3, 4, 5, 6, 7) 
(1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7)

(3)元组连接

元组中的元素值是不允许修改的,但可以对元组进行连接组合,实例如下:

tup1 = (12, 34, 56) 
tup2 = (78, 90) 
#tup1[0] = 100       #修改元组元素操作是非法的
tup3 = tup1 + tup2   #连接元组,创建一个新的元组
print (tup3) 

以上实例输出结果:(12, 34, 56, 78, 90)

(4)删除元组

元组中的元素值是不允许删除的,但可以使用del语句来删除整个元组,实例如下:

tup = ('中国', '美国', 1997, 2000); 
print (tup) 
del tup 
print ("After deleting tup : ") 
print(tup)

以上实例元组被删除后,输出变量会有异常信息,输出如下所示:

('中国', '美国', 1997, 2000)
After deleting tup :
NameError: name 'tup' is not defined

(5)元组与列表转换

因为元组值不能改变,所以可以将元组转换为列表从而可以改变数据的值。实际上列表、元组和字符串之间是可以互相转换的,但需要使用三个函数,str()、tuple()和list()。

可以使用下面的方法将元组转换为列表:

列表对象=list(元组对象)

tup=(1, 2, 3, 4, 5)
list1= list(tup)         #元组转为列表
print(list1)             #返回[1, 2, 3, 4, 5]

可以使用以下方法将列表转换为元组:

元组对象= tuple(列表对象)

nums=[1, 3, 5, 7, 8, 13, 20] 
print (tuple(nums))           #列表转为元组,返回(1, 3, 5, 7, 8, 13, 20) 

将列表转换成字符串如下:

nums=[1, 3, 5, 7, 8, 13, 20] 
str1= str(nums)        #列表转为字符串,返回包含中括号及逗号的'[1, 3, 5, 7,  
                        8, 13, 20]'字符串
print (str1[2])        #打印出逗号,因为字符串中索引号2的元素是逗号
num2=['中国', '美国', '日本', '加拿大'] 
str2= "%" 
str2= str2.join(num2)  #用百分号连接起来的字符串——'中国%美国%日本%加拿大' 
str2= "" 
str2= str2.join(num2)  #用空字符连接起来的字符串——'中国美国日本加拿大'

3. 字典

Python字典(dict)是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典也被称作关联数组或哈希表。

(1)创建字典

字典由键和对应值(key=>value)成对组成。字典的每个键/值对里面键和值用冒号分割,键/值对之间用逗号分割,整个字典包括在花括号中。基本语法如下:

d = {key1 : value1, key2 : value2 }

注意:键必须是唯一的,但值不必唯一。值可以取任何数据类型,但键必须是不可变的,如字符串、数字或元组。

下面是一个简单的字典实例:

dict = {'xmj' : 40, 'zhang' : 91, 'wang' : 80}

也可创建字典如下:

dict1 = { 'abc': 456 };
dict2 = { 'abc': 123, 98.6: 37 };

字典有如下特性:

① 字典值可以是任何Python对象,如字符串、数字、元组等;

② 不允许同一个键出现两次。如果创建时同一个键被赋值两次,则后一个值会覆盖前面的值;

dict = {'Name': 'xmj', 'Age': 17, 'Name': 'Manni'};
print("dict['Name']: ", dict['Name']);

以上实例输出结果:

dict['Name']: Manni

③ 键不可变,所以可以用数字、字符串或元组充当,但不能用列表,实例如下:

dict = {['Name']: 'Zara', 'Age': 7};

以上实例输出错误结果:

Traceback (most recent call last): 
 File "<pyshell#0>", line 1, in <module> 
    dict = {['Name']: 'Zara', 'Age': 7} 
TypeError: unhashable type: 'list'

(2)访问字典里的值

访问字典里的值时把相应的键放入方括号中,实例如下:

dict = {'Name': '王海', 'Age': 17, 'Class': '计算机一班'} 
print ("dict['Name']: ", dict['Name']) 
print ("dict['Age']: ", dict['Age'])

以上实例输出结果:

dict['Name']:  王海
dict['Age']:  17

如果用字典里不存在的键访问数据,则会输出错误信息:

dict = {'Name': '王海', 'Age': 17, 'Class': '计算机一班'} 
print ("dict['sex']: ", dict['sex'] )

由于没有sex键,以上实例输出错误结果:

Traceback (most recent call last): 
 File "<pyshell#10>", line 1, in <module> 
    print ("dict['sex']: ", dict['sex'] ) 
KeyError: 'sex''

(3)修改字典

向字典添加新内容的方法是增加新的键/值对,修改或删除已有键/值对,实例如下:

dict = {'Name': '王海', 'Age': 17, 'Class': '计算机一班'} 
dict['Age'] = 18                #更新键/值对(update existing entry) 
dict['School'] = "中原工学院"     #增加新的键/值对(add new entry) 
print ("dict['Age']: ", dict['Age'] ) 
print ( "dict['School']: ", dict['School']; 

以上实例输出结果:

dict['Age']:  18 
dict['School']:  中原工学院

(4)删除字典元素

del()方法允许使用键从字典中删除元素(条目),clear()方法会清空字典所有元素。

显式删除一个字典用del命令,实例如下:

dict = {'Name': '王海', 'Age': 17, 'Class': '计算机一班'} 
del dict['Name']             #删除键是'Name'的元素(条目) 
dict.clear()                 #清空词典所有元素
del dict                     #删除词典,用del后字典不再存在

(5)in运算

字典里的in运算用于判断某键是否包含在字典里,对于value值则不适用。功能与has_key(key)方法相似。

dict = {'Name': '王海', 'Age': 17, 'Class': '计算机一班'} 
print  ('Age' in dict )      #等价于print (dict.has_key('Age' ) )

以上实例输出结果:

True

(6)获取字典中的所有值

dict1.values( )以列表返回字典中的所有值。

dict = {'Name': '王海', 'Age': 17, 'Class': '计算机一班'} 
print  (dict.values ())

以上实例输出结果:

[17, '王海', '计算机一班']

(7)items()方法

items()方法把字典中每对key和value组成一个元组,并把这些元组放在列表中返回。

dict = {'Name': '王海', 'Age': 17, 'Class': '计算机一班'} 
for key,value in dict.items(): 
     print( key,value) 

以上实例输出结果:

Name 王海
Class 计算机一班
Age 17

需要注意,字典打印出来的顺序与创建之初的顺序不同,这不是错误。字典中各个元素并没有顺序之分(因为不需要通过位置查找元素),因此,存储元素时进行了优化,使字典的存储和查询效率最高。这也是字典和列表的另一个区别:列表保持元素的相对关系,即序列关系;而字典是完全无序的,也称为非序列。如果想保持一个集合中元素的顺序,则需要使用列表,而不是字典。

4. 集合

集合(set)是一个无序不重复元素的序列。集合基本功能是进行成员关系测试和删除重复元素。

(1)创建集合

可以使用大括号({})或者set()函数创建集合,注意:创建一个空集合必须用set()而不是{ },因为{ }是用来创建一个空字典。

student = {'Tom', 'Jim', 'Mary', 'Tom', 'Jack', 'Rose'} 
print(student)   #输出集合,重复的元素被自动去掉

以上实例输出结果:

{'Jack', 'Rose', 'Mary', 'Jim', 'Tom'}

(2)成员测试

if('Rose' in student) : 
      print('Rose 在集合中')
else : 
      print('Rose 不在集合中')

以上实例输出结果:

Rose 在集合中

(3)集合运算

可以使用“-”“|”“&”运算符分别进行集合的差集、并集、交集运算。

#set可以进行集合运算
a = set('abcd') 
b = set('cdef') 
print(a) 
print("a和b的差集:", a - b)      #a和b的差集
print("a和b的并集:", a | b)      #a和b的并集
print("a和b的交集:", a & b)      #a和b的交集
print("a和b中不同时存在的元素:", a ^ b)     #a和b中不同时存在的元素

以上实例输出结果:

{'a', 'c', 'd', 'b'} 
a和b的差集:{'a', 'b'} 
a和b的并集:{'b', 'a', 'f', 'd', 'c', 'e'} 
a和b的交集:{'c', 'd'} 
a和b中不同时存在的元素:{'a', 'e', 'f', 'b'}

1.2.3 Python控制语句

Python程序中的执行语句,默认是按照书写顺序依次执行的,此时的语句是顺序结构的。但是,仅有顺序结构还是不够的,因为有时候我们需要根据特定的情况,有选择地执行某些语句,这时我们就需要一种选择结构的语句。另外,有时候我们还可以在给定条件下反复执行某些语句,这时我们称这些语句是循环结构的。有了这三种基本的结构,我们就能够构建更加复杂的程序了。

1. 选择结构

三种基本程序结构中的选择结构,可用if语句、if…else语句和if…elif…else语句实现。

if语句是一种单选结构,它选择的是做与不做。if语句的语法形式如下所示:

if 表达式:
        语句1

if语句的流程图如图1-7所示。

图1-7 if语句的流程图

而if…else语句是一种双选结构,是在两种备选行动中选择哪一个。if…else语句的语法形式如下所示:

if 表达式:
    语句1  
else :
    语句2

if…else语句的流程图如图1-8所示。

图1-8 if…else语句的流程图

【例1-1】输入一个年份,判断其是否为闰年。闰年的年份必须满足以下两个条件之一:

(1)能被4整除,但不能被100整除的年份都是闰年;

(2)能被400整除的年份都是闰年。

分析:设变量year表示年份,判断year是否满足以下表达式。

条件(1)的逻辑表达式是:year%4 == 0&&year%100 != 0。

条件(2)的逻辑表达式是:year%400 == 0。

两者取“或”,即得到判断闰年的逻辑表达式为:

(year%4 == 0 and year%100 != 0)  or  year%400 == 0

程序代码:

year = int(input('输入年份:'))     #输入x,input()获取的是字符串,所以需要转换
                                  #成整型
if  year%4 == 0 and year%100 != 0 or year%400 == 0: #注意运算符的优先级
    print(year, "是闰年") 
else: 
    print( year, "不是闰年")

判断闰年后,也可以输入某年某月某日,判断这一天是这一年的第几天。以3月5日为例,应该先把前两个月的天数加起来,然后再加上5即为本年的第几天。特殊情况是闰年,在输入月份大于3时需考虑多加一天。

程序代码:

year = int(input('year:'))               #输入年
month = int(input('month:'))             #输入月
day = int(input('day:'))                 #输入日
months = (0,31,59,90,120,151,181,212,243,273,304,334) 
if 0 <= month <= 12: 
     sum = months[month - 1] 
else: 
     print( '月份输入错误') 
sum += day 
leap = 0 
if (year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0)): 
     leap = 1 
if (leap == 1) and (month > 2): 
     sum += 1 
print('这一天是这一年的第%d天'%sum) 

有时,我们需要在多组动作中选择一组执行,这时就会用到多选结构,对Python语言来说,多选结构就是if…elif…else语句。该语句的语法形式如下所示:

if 表达式1 :
    语句1 
elif 表达式2 :
    语句2 
    …… 
elif 表达式n :
    语句n 
else : 
    语句n+1

注意,最后一个elif子句之后的else子句没有进行条件判断,它用于处理与前面所述条件都不匹配的情况,所以else子句必须放在最后。if…elif…else语句的流程图如图1-9所示。

图1-9 if…elif…else语句的流程图

【例1-2】输入学生的成绩score,按分数输出其等级:score≥90为优,90>score≥80为良,80>score≥70为中等,70>score≥60为及格,score<60为不及格。

score=int(input("请输入成绩"))      #int()转换字符串为整型
if score >= 90:  
      print("优") 
elif  score >= 80:  
      print("良")  
elif  score >= 70: 
      print("中等") 
elif  score >= 60:  
      print("及格") 
else : 
      print("不及格")

说明:在三种选择语句中,条件表达式都是必不可少的组成部分。那么,哪些表达式可以作为条件表达式呢?一般地,最常用的是关系表达式和逻辑表达式,如:

if  a == x  and  b == y : 
     print ("a = x, b = y")

除此之外,条件表达式可以是任何数值类型表达式,当条件表达式的值为零时,表示条件为假;当条件表达式的值为非零时,表示条件为真。甚至字符串也可以:

if  'a':   #'abc':也可以,被认为是True 
     print ("a = x, b = y")

另外,C语言是用花括号{}来区分语句体,但是Python的语句体是用缩进形式来表示的,如果缩进不正确,则会导致逻辑错误。

2. 循环结构

程序在一般情况下是按顺序执行的。编程语言提供了各种控制结构,允许更复杂的执行路径。循环语句允许我们执行一个语句或语句组多次,Python提供了for循环和while循环(在Python中没有do…while循环)。

(1)while语句

Python中的while语句用于循环执行程序,即在某条件下,循环执行某段程序,以处理需要重复处理的相同任务。其基本形式为:

while 判断条件:
   执行语句

执行语句可以是单个语句或语句块。判断条件可以是任何表达式,任何非零或非空的值均为True;当判断条件为False时,循环结束。Which语句的流程图如图1-10所示。

图1-10 while语句的流程图

同样地,需要注意冒号和缩进。例如:

count = 0
while count < 5: 
   print ('The count is:', count)  
   count = count + 1
print ("Good bye!" )

(2)for语句

for语句可以遍历任何序列的项目,如一个列表、元组或者一个字符串。for循环的语法格式如下:

for 循环索引值 in 序列
       循环体

for循环把列表中的元素遍历出来。例如:

fruits = ['banana', 'apple',  'mango'] 
for fruit in fruits:         #第二个实例
    print ( '元素 :', fruit)
print( "Good bye!" )

运行上述代码后会依次打印fruits中的每一个元素,程序运行结果:

元素:banana
元素:apple
元素:mango
Good bye!

【例1-3】计算1~10的整数之和,可以用一个sum变量进行累加。

程序代码:

sum = 0 
for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]: 
      sum = sum + x 
print(sum)

如果要计算1~100的整数之和,从1写到100十分烦琐。Python提供了一个range()内置函数,可以生成一个整数序列,再通过list()函数可以转换为list列表。

例如,range(0, 5)或range(5)生成的序列是从0开始小于5的整数,但不包括5。结果如下:

>>> list(range(5)) 
[0, 1, 2, 3, 4]

range(1, 101)就可以生成1~100的整数序列,计算1~100的整数之和如下:

sum = 0 
for x in range(1,101): 
      sum = sum + x 
print(sum)

(3)continue和break语句

break语句在while循环和for循环中都可以使用,一般放置于if选择结构中,一旦break语句被执行,将使整个循环提前结束。

continue语句的作用是终止当前循环,并忽略continue之后的语句,然后回到循环的顶端,提前进入下一次循环。

注意:除非break语句让代码更简单或更清晰,否则不要轻易使用。

【例1-4】continue和break用法示例。

#continue 和 break 用法
i = 1 
while i < 10:    
    i += 1 
    if i%2 > 0:       #非双数时跳过输出
          continue 
    print (i)         #输出双数2、4、6、8、10 
 
i = 1 
while 1:              #循环条件为1必定成立
    print (i)         #输出1~10 
    i += 1 
    if i > 10:        #当i大于10时跳出循环
          break

在Python程序开发过程中,开发者将完成某一特定功能并经常使用的代码编写成函数,放在函数库(模块)中供大家选用,在需要使用时可直接调用。编程人员要善于使用函数,提高编码效率。

1.2.4 Python函数与模块

当执行某些任务时,如求一个数的阶乘,需要在一个程序中不同位置重复执行时,这样造成代码的重复率高,应用程序代码烦琐。解决这个问题的方法就是使用函数。无论在哪种编程语言当中,函数(在类中称作方法,意义是相同的)都扮演着至关重要的角色。模块是Python的代码组织单元,它将函数、类和数据封装起来以便重用,模块往往对应Python程序文件、Python标准库和第三方提供的大量的模块。

1. 函数定义

在Python中,函数定义的基本形式如下:

def  函数名(函数参数): 
    函数体
    return 表达式或者值

在这里需要注意以下几点:

(1)在Python中采用def关键字进行函数的定义,不用指定返回值的类型;

(2)函数参数可以是零个、一个或者多个,同样地,函数参数也不用指定参数类型,因为在Python中变量都是弱类型的,Python会自动根据值来维护其类型;

(3)Python函数的定义中缩进部分是函数体;

(4)函数的返回值是通过函数中的return语句获得的。return语句是可选的,它可以在函数体内任何地方出现,表示函数调用执行到此结束。如果没有return语句,则会自动返回None(空值);如果有return语句,但是return后面没有接表达式或者值,也会返回None(空值)。

下面定义三个函数:

def printHello():            #打印'hello'字符串
     print ('hello') 
    
def printNum():              #输出数值0~9 
     for i in range(0,10): 
            print (i) 
     return 
        
def add(a,b):                #实现两个数的和
     return a+b

2. 函数的使用

在定义了函数之后,我们就可以使用该函数了。但是在Python中要注意一个问题,就是在Python中不允许前向引用,即在函数定义之前,不允许调用该函数。实例如下:

print (add(1,2)) 
def add(a,b): 
   return a+b

这段程序运行的错误提示如下:

Traceback (most recent call last): 
 File "C:/Users/xmj/4-1.py", line 1, in <module> 
    print (add(1,2)) 
NameError: name 'add' is not defined

从报错信息可以知道,名字为“add”的函数未进行定义。所以在任何时候调用某个函数,必须确保其定义在调用之前。

【例1-5】编写函数,计算形式如a + aa + aaa + aaaa +…+ aaa…aaa的表达式的值,其中,a为小于10的自然数。例如,2+22+222+2222+22222(此时n=5),a、n由用户从键盘输入。

分析:关键是计算出求和中每一项的值。容易看出每一项都是前一项扩大10倍后加a。

程序代码:

def  sum (a, n): 
    result, t = 0, 0        #同时将result、t赋值为0,这种形式比较简洁
    for i in range(n): 
           t = t*10 + a 
           result += t 
    return result 
#用户输入两个数字
a = int(input("输入a: ")) 
n = int(input("输入n: ")) 
print(sum(a, n)) 

程序运行结果:

输入a: 2↙ 
输入n: 5↙ 
24690

3. 闭包(closure)

在Python中,闭包指函数的嵌套。可以在函数内部定义一个嵌套函数,将嵌套函数视为一个对象,所以可以将嵌套函数作为定义它的函数的返回结果。

【例1-6】使用闭包的例子。

def func_lib(): 
     def add(x, y): 
           return x+y 
     return add        #返回函数对象
fadd = func_lib() 
print(fadd(1, 2))

在函数func_lib()中定义了一个嵌套函数add(x, y),并作为函数func_lib()的返回值。运行结果为3。

4. 函数的递归调用

函数在执行的过程中直接或间接调用自己本身,称为递归调用。Python语言允许递归调用。

【例1-7】求1~5的平方和。

def f(x): 
    if x==1:                 #递归调用结束的条件
         return 1 
    else: 
         return(f(x-1)+x*x)  #调用f()函数本身
print(f(5))

5. 模块

模块(module)能够有逻辑地组织Python代码段,可将相关的代码分配到一个模块里,让代码更简明实用。简单地说,模块就是一个保存了Python代码的文件。模块能定义函数、类和变量。

在Python中,模块与C语言中的头文件以及Java中的包很类似,如在Python中要调用sqrt函数,必须用import关键字引入math这个模块。

(1)导入某个模块

在Python中用关键字import来导入某个模块。方式如下:

import 模块名        #导入模块

比如,要引用模块math,就可以在文件最开始的地方用import math来导入。

在调用模块中的函数时,必须这样调用:

模块名.函数名

例如:

import math          #导入math模块
print ("50的平方根:", math.sqrt(50))

为什么必须加上模块名这样调用呢?因为可能存在这样一种情况:在多个模块中含有相同名称的函数,此时如果只是通过函数名来调用,则解释器无法知道到底要调用哪个函数。因此,如果像上述这样导入模块时,调用函数必须加上模块名。

有时我们只需要用到模块中的某个函数,则只需要引入该函数即可,此时可使用from语句:

from 模块名 import 函数名1,函数名2…

通过这种方式引入时,调用函数时只能给出函数名,不能给出模块名,但是当两个模块中含有相同名称函数时,后面一次引入会覆盖前一次引入。

也就是说,假如模块A中有函数fun(),在模块B中也有函数fun(),如果引入A中的fun()在先、B中的fun()在后,那么,当调用fun()函数时,系统会去执行模块B中的fun()函数。

如果想一次性导入math中所有的内容,还可以通过如下代码实现:

from math import *

这是一种简单导入模块中的所有项目的方式,但最好不要过多地使用这种方式。

(2)定义自己的模块

在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。

比如,有这样一个文件fibo.py,在fibo.py中定义了三个函数add()、fib()和fib2():

#fibo.py 
#斐波那契(fibonacci)数列模块
def fib(n):    #定义到 n 的斐波那契数列
     a, b = 0, 1 
     while b < n: 
           print(b, end=' ') 
           a, b = b, a+b 
     print() 
def fib2(n): #返回到 n 的斐波那契数列
     result = [] 
     a, b = 0, 1 
     while b < n: 
           result.append(b) 
           a, b = b, a+b 
     return result 
def add(a,b): 
     return a+b

那么,在其他文件(如test.py)中就可以按如下方式来使用:

#test.py 
import fibo

加上模块名称来调用函数:

fibo.fib(1000) #结果是1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 
fibo.fib2(100) #结果是[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] 
test.add(2,3)  #结果是5

当然也可以通过from fibo import add, fib, fib2来引入。

还可以直接使用函数名来调用函数:

fib(500)   #结果是1 1 2 3 5 8 13 21 34 55 89 144 233 377

若列举fibo模块中定义的属性列表如下:

import fibo 
dir(fibo)     #得到自定义模块fibo中定义的的变量和函数

输出结果:['__name__', 'fib', 'fib2', 'add']。