资源简介
(共68张PPT)
Python少儿编程
第五章 强大的函数积木
目录
1.1
创建积木
1.2
灵活的积木参数
1.3
积木嵌套积木
1.4
我的地盘听我的
1.5
隐藏名字的积木
1.6
积木盒子
PART 01
创建积木
函数的定义
1.1
Python中定义函数的基本语法格式如下。
其中,def是Python的关键字,用于定义函数;函数名可以是任何有效的Python标识符;形式参数列表(简称形参)是调用该函数时传递给函数的参数,可以是零个、一个或多个,当传递多个参数时各参数之间使用逗号隔开,[ ]表示可选内容;函数体是每次调用函数执行的代码,由一行或多行语句组成。定义函数时须注意以下几点。
(1)当函数参数为零个时,也必须保留一对空的圆括号。
(2)圆括号后面的冒号不能省略。
(3)函数体相对于def关键字必须保持一定的空格缩进。
def 函数名([形式参数列表]):
函数体
函数的调用
1.2
函数定义后,须调用函数才能执行函数体,实现特定的功能。函数调用的基本语法格式如下。
函数名([实际参数列表])
其中,实际参数列表(简称实参)表示要传递给函数的具体值。
【例5-1】 小蓝的日常活动。
【问题分析】 定义函数封装日常活动,然后按作息时间调用函数。例如,定义eat()函数,输出“吃饭......”,定义school()函数输出“上课......”等。
函数的调用
1.2
【参考代码】
def eat(): #定义eat()函数,表示吃饭
print('吃饭......')
def school(): #定义school()函数,表示上课
print('上课......')
def homework(): #定义homework()函数,表示做作业
print('做作业......')
def exercise(): #定义exercise()函数,表示运动
print('运动......')
print('小蓝的日常活动‘)
函数的调用
1.2
【参考代码】(续)
#按作息时间调用函数
eat()
school()
eat()
school()
exercise()
eat()
homework()
函数的调用
1.2
【运行结果】 程序运行结果如图5-1所示。
图5-1 例5-1程序运行结果
【程序说明】 由于函数只有在调用时才执行,因此,前面定义函数的代码不会直接执行。当调用函数时,当前执行暂停,转去执行函数体。当函数执行完毕后,重新回到调用函数位置,继续执行后面的语句。
函数的返回值
1.3
函数除了可以在函数体中直接输出数据,还可以返回一个或多个值,称为函数的返回值。在Python中,函数使用return语句返回值。
return语句用于退出函数并将程序返回到函数调用的位置继续执行,同时返回零个、一个或多个值。
【例5-2】 根据时间判断吃早饭、午饭还是晚饭。
【问题分析】定义eat()函数,参数为时间,根据时间范围判断吃早饭、午饭还是晚饭,返回字符串。
函数的返回值
1.3
【参考代码】
def eat(time): #定义eat()函数,参数为时间time
#如果time在6点~8点,返回吃早饭
if time >= 6 and time <= 8:
return '{}点吃早饭......'.format(time)
#如果time在11点~13点,返回吃午饭
elif time >= 11 and time <= 13:
return '{}点吃午饭......'.format(time)
#如果time在17点~19点,返回吃晚饭
elif time >= 17 and time <= 19:
return '{}点吃晚饭......'.format(time)
else: #不满足上述条件,返回不在吃饭时间
return '不在吃饭时间'
time = int(input('请输入时间:')) #输入时间,并转换为int型赋给time
print(eat(time)) #调用eat()函数,输出返回值
函数的返回值
1.3
【运行结果】 程序运行结果如图5-2所示。
图5-2 例5-2程序运行结果
如果函数没有return语句,将默认以return None结束,即返回空值。函数也可使用return语句返回多个值,每个值之间使用逗号隔开。函数调用后,返回值以元组形式保存。
函数的返回值
1.3
【例5-3】 计算小蓝的最低成绩、最高成绩和总成绩。
【问题分析】 定义函数score_compute(),参数为小蓝的各科成绩,使用min()函数计算最小值,max()函数计算最大值,然后返回最小值、最大值及总成绩。
【参考代码】
#定义score_compute()函数
def score_compute(chinese, math, english):
#使用min()函数计算最小值,并赋给score_min
score_min = min(chinese, math, english)
#使用max()函数计算最大值,并赋给score_max
score_max = max(chinese, math, english)
#计算总成绩,并赋给score_total
score_total = chinese + math + english
#返回score_min、score_max和score_total
return score_min, score_max, score_total
函数的返回值
1.3
【参考代码】(续)
#输入各科成绩
chinese = float(input('请输入语文成绩:'))
math = float(input('请输入数学成绩:'))
english = float(input('请输入英语成绩:'))
#调用score_compute()函数,并将返回值赋给score
score = score_compute(chinese, math, english)
print(score, type(score)) #输出score及其类型
print('小蓝的最低成绩为:', score[0],
'\n小蓝的最高成绩为:', score[1],
'\n小蓝的总成绩为:', score[2]) #输出最低成绩、最高成绩和总成绩
函数的返回值
1.3
【运行结果】 程序运行结果如图5-3所示。
图5-3 例5-3程序运行结果
【程序说明】 本例题中return语句返回多个值,通过语句“print(score, type(score))”输出变量score及其类型,可以看出,多个值以元组形式保存。因此,可以通过下标来访问元组中的元素,从而分别得到最低成绩、最高成绩和总成绩。
PART 02
灵活的积木参数
实参和形参
2.1
定义函数时,圆括号内的参数为形参;调用函数时,圆括号内的参数为实参,根据参数的不同数据类型,将实参的值或引用传递给形参。
在Python中,函数参数的数据类型可分为不可变数据类型(如整数、浮点数、字符串、元组等)和可变数据类型(如列表、字典、集合等)。
实参和形参
2.1
【例5-4】 阅读下面程序,分析输出结果。
【参考代码】
def change(a):
a = 10
print('函数内a =', a)
a = 2
change(a)
print('函数外a =', a)
当参数数据类型为不可变数据类型时,在函数内直接修改形参的值不会影响实参。
实参和形参
2.1
【运行结果】 程序运行结果如图5-4所示。
图5-4 例5-4程序运行结果
【程序说明】 从运行结果可以看出,在函数内修改了形参a的值,但是当函数运行结束后,实参a的值并没有改变。
实参和形参
2.1
【例5-5】 阅读以下程序,分析输出结果。
【参考代码】
def change(mylist):
mylist.append([1, 2, 3, 4])
print('函数内mylist = ', mylist)
mylist = [10, 20, 30]
print('调用函数前,函数外mylist = ', mylist)
change(mylist)
print('调用函数后,函数外mylist = ', mylist)
但当参数数据类型为可变数据类型时,在函数内使用下标或其他方式增加、删除或修改元素时,实参也会相应地修改。
实参和形参
2.1
【运行结果】 程序运行结果如图5-5所示。
图5-5 例5-5程序运行结果
【程序说明】 从运行结果可以看出,在函数内修改了形参mylist的元素,当函数运行结束以后,实参mylist的值也修改了。
参数类型
2.2
1.位置参数
【例5-6】 定制问候语。对不同的人说不同的问候语。
【参考代码】
def greet(name, say):
print(name, say)
greet('小蓝', '你好!')
greet('hello!', '小舞')
greet('小明')
位置参数是比较常用的形式,调用函数时,实参和形参的顺序应一致,且实参和形参的数量必须相同。
【问题分析】 定义函数greet(name, say),其中,name表示人名,say表示问候语。
参数类型
2.2
1.位置参数
【运行结果】 程序运行结果如图5-6所示。
图5-6 例5-6程序运行结果
【程序说明】 当第一次调用greet()函数时,将实参“小蓝”和“你好!”分别传递给形参name和say,实现输出。当第二次调用greet()函数时,将实参“hello!”和“小舞”分别传递给形参name和say,虽然也可以正常输出,但实参和形参的含义不一致,将会影响数据的理解和使用,因此,位置参数的实参和形参的顺序须一致。当第三次调用greet()函数时,实参和形参的数量不同,程序运行到该条语句时提示错误信息(缺少要求的位置参数say)。
参数类型
2.2
2.默认值参数
在定义函数时,可以为函数的参数设置默认值,此参数称为默认值参数。在调用带默认值参数的函数时,可以不用为默认值参数传值,此时函数将会直接使用函数定义时设置的默认值,也可以通过显式赋值来替换其默认值。定义带有默认值参数函数的基本语法格式如下。
def 函数名(……,形参名=默认值):
函数体
参数类型
2.2
2.默认值参数
【例5-7】 使用不可变数据类型设置默认问候语。
【参考代码】
def greet(name, say='hi!'): #设置默认问候语为“hi!”
print(name, say)
print(greet.__defaults__) #输出函数默认值参数
greet('小蓝', '你好!')
greet('小舞', 'hello!')
greet('小红')
greet('小明')
参数类型
2.2
2.默认值参数
【运行结果】 程序运行结果如图5-7所示。
图5-7 例5-7程序运行结果
参数类型
2.2
2.默认值参数
【例5-8】 使用可变数据类型设置默认问候语。
【参考代码】
def greet(name, say=['hi!']): #使用列表设置默认问候语
say.append('见到你很开心') #列表添加元素
print(name, say)
greet('小蓝', ['你好!'])
greet('小舞', ['hello!'])
greet('小明')
greet('小红')
多次调用函数且不为默认值参数传递值时,默认值参数只在定义时进行一次解释和初始化,而对于列表、字典等可变数据类型的默认值参数,可能会导致逻辑错误。因此,一般来说,要避免使用列表、字典、集合或其他可变数据类型作为函数参数的默认值。
参数类型
2.2
2.默认值参数
【运行结果】 程序运行结果如图5-8所示。
图5-8 例5-8程序运行结果
【程序说明】 使用列表作为默认值参数,且连续多次调用该函数而不给该参数传值时,再次调用将保留上一次调用结果。因此,执行语句“greet('小红')”时,输出的列表say中包含两个“见到你很开心”,即在上一次调用结果的基础上增加了同一元素。
参数类型
2.2
2.默认值参数
【例5-9】 使用变量设置默认问候语。
【参考代码】
s = 'hi!'
def greet(name, say=s):
print(name, say)
s = '你好!'
greet('小蓝')
此外,如果在定义函数时某个参数的默认值为一个变量,那么参数的默认值只取决于函数定义时该变量的值。
参数类型
2.2
2.默认值参数
【运行结果】 程序运行结果如图5-9所示。
图5-9 例5-9程序运行结果
【程序说明】 函数的默认值参数只会初始化一次,即在函数定义时就确定值,所以,在定义函数greet()时,s的值为“hi!”,因此输出为“小蓝 hi!”。
参数类型
2.2
3.关键字参数
【例5-10】 使用关键字参数设置问候语。
【参考代码】
def greet(name, say):
print(name, say)
greet('你好!', '小蓝')
greet(say='hello!', name='小舞')
关键字参数是指调用函数时按参数名传递值。使用关键字参数允许函数调用时参数的顺序与定义时不一致,Python解释器能够使用参数名匹配参数值。
【运行结果】 程序运行结果如图5-10所示。
图5-10 例5-10程序运行结果
参数类型
2.2
4.不定长参数
通常在定义一个函数时,若希望函数能够处理比定义时更多的参数,此时可在函数中使用“*”或“**”符号表示不定长参数,其基本语法格式如下。
def 函数名([形参列表,] *args, **kwargs):
函数体
其中,“*args”和“**kwargs”为不定长参数,“*”表示接收任意多个实参并将其放在一个元组中,“**”表示接收显式赋值的多个实参并将其放入字典中,实参格式类似关键字参数。两种形式可只使用其中一种或同时使用。
参数类型
2.2
4.不定长参数
【例5-11】 使用不定长参数同时和多人说问候语。
【参考代码】
def greet(say, *names, **name_say):
print('say:', say)
print('names:', names)
print('name_say:', name_say)
for name in names:
print(name, say)
for key in name_say.keys():
print(key, name_say[key])
greet('hi!', '小蓝', '小舞', 小红='你好!', 小明='hello!')
参数类型
2.2
4.不定长参数
【运行结果】 程序运行结果如图5-11所示。
图5-11 例5-11程序运行结果
【程序说明】 在调用greet()函数时,传入多个值,这些值会自左往右依次匹配函数定义时的参数,首先将“hi!”传递给say,接着将“'小蓝', '小舞'”组成一个元组,传递给names,最后将“小红='你好!', 小明='hello!'”转换为字典传递给name_say。
PART 03
积木嵌套积木
函数的嵌套
3.1
Python允许函数的嵌套定义,即在函数内可以再定义另外一个函数。例如,在fun1()函数中嵌套定义fun2()函数,可以用下面代码实现。
def fun1(): #定义fun1()函数
print('************')
def fun2(): #嵌套定义fun2()函数
print('Hello world!')
fun2() #调用fun2()函数
fun1() #调用fun1()函数
这里需要注意的是,fun2()函数只在定义开始到fun1()函数结束范围内有效。
Python还允许在一个函数中调用另外一个函数,这就是函数的嵌套调用。例如,上述代码中,在fun1()函数中嵌套调用fun2()函数。当然,函数也可以嵌套调用外部定义的另一个函数。
函数的嵌套
3.1
【例5-12】 计算1!+2!+3!+…+10!的值并输出。
【问题分析】 使用函数的嵌套调用实现,定义sum()函数计算累加,以及fac()函数计算阶乘。执行时首先调用sum()函数,然后sum()函数中再调用fac()函数。
【参考代码】
def fac(k): #定义fac()函数,计算阶乘
i = 2
t = 1
while i <= k:
t *= i
i += 1
return t #返回阶乘结果
函数的嵌套
3.1
【参考代码】(续)
def sum(n): #定义sum()函数,计算累加
s = 0
i = 1
while i <= n:
s = s + fac(i) #调用fac()函数
i += 1
return s #返回累加结果
print('1!+2!+3!…10!=', sum(10)) #调用sum()函数
【运行结果】 程序运行结果如图5-12所示。
图5-12 例5-12程序运行结果
函数的递归
3.2
Python支持函数的递归调用,它是一种函数嵌套调用的特殊形式,即函数直接或间接地调用其本身。直接递归调用是在函数中调用自身,例如:
def fun(): #定义fun()函数
fun() #调用fun()函数
间接递归调用是在fun()函数中调用fun1()函数,而fun1()函数又调用了fun()函数,例如:
def fun(): #定义fun()函数
fun1() #调用fun1()函数
def fun1(): #定义fun1()函数
fun() #调用fun()函数
函数的递归
3.2
【例5-13】 计算斐波那契数列的第n项。斐波那契数列从第3项开始,元素的值为前两个元素相加得到,如1、1、2、3、5、8、13、21、34、55。
【问题分析】 定义函数fib(n)计算数列的第n项,由题可知fib(n)=fib(n-1)+fib(n-2),因此可使用递归函数解决该问题。
【参考代码】
def fib(n):
if n == 1:
return 1
elif n == 2:
return 1
else:
return fib(n - 1) + fib(n - 2)
n = int(input('请输入一个正整数:'))
print('斐波那契数列的第{}项为:{}'.format(n, fib(n)))
函数的递归
3.2
【运行结果】 程序运行结果如图5-13所示。
图5-13 例5-13程序运行结果
【程序说明】 本例题中,n=1和n=2时都返回1,这就是该函数的终止条件。当n等于5时,该程序的执行过程如图5-14所示。
图5-14 计算斐波那契数列第5项的执行过程
PART 04
我的地盘听我的
局部变量和全局变量
4.1
局部变量是定义在函数内的变量,只能在变量定义开始到函数结束的范围内使用,它与函数外具有相同名称的其他变量没有任何关系。不同函数中,可以使用相同名称的局部变量,它们代表不同的对象,互不干扰。此外,函数的形参也属于局部变量,作用范围仅限于函数内部。
在函数外定义的变量称为全局变量,它在变量定义开始到整个程序结束的范围内有效。
局部变量和全局变量
4.1
【例5-14】 分析下面程序的运行结果。
【问题分析】 定义函数fib(n)计算数列的第n项,由题可知fib(n)=fib(n-1)+fib(n-2),因此可使用递归函数解决该问题。
【参考代码】
num = 3 #创建全局变量num
def fun(): #定义fun()函数
num = 5 #创建局部变量num
print('函数内局部变量num的值:', num) #输出局部变量num的值
fun() #调用fun()函数
print('函数外全局变量num的值:', num) #输出全局变量num的值
局部变量和全局变量
4.1
【运行结果】 程序运行结果如图5-15所示。
图5-15 例5-14程序运行结果
【程序说明】 在此程序中,定义了两个名为num的变量。在函数内的num变量为局部变量,调用函数后num的值为5,故函数内的输出为5;离开函数后,在函数内定义的num变量失效,此时全局变量num有效,故函数外的输出为3。
global和nonlocal关键字
4.2
使用global关键字可分为以下两种情况。
(1)变量已在函数外创建,如果需要在函数内使用或修改该变量,须在函数内使用关键字global声明该全局变量。
(2)变量没有在函数外创建,在函数内直接使用global关键字声明全局变量,然后赋值,调用该函数后,会创建新的全局变量,在函数外也可以使用或修改该变量。
1. global关键字
global和nonlocal关键字
4.2
1. global关键字
【例5-15】 分析以下程序的运行结果。
【参考代码】
num = 5 #创建全局变量num
def fun(): #定义fun()函数
global num #使用global关键字声明num
num += 1 #num加1
print('函数内num的值:', num) #函数内输出num的值
fun() #调用fun()函数
print('函数外num的值:', num) #函数外输出num的值
【运行结果】 程序运行结果如图5-16所示。
图5-16 例5-15程序运行结果
global和nonlocal关键字
4.2
1. global关键字
【程序说明】 在fun()函数外创建全局变量num,然后在fun()函数内使用global关键字声明num,此时,函数内的num就是函数外的全局变量num。因此,在函数内num的初始值为5,执行“num += 1”语句后,num的值为6,函数外的num值也为6。
如果没有“global num”这条语句,函数内的num为局部变量,执行“num += 1”这条语句前须对num赋值,否则,执行程序时将提示“local variable 'num' referenced before assignment”错误信息,即“在赋值前引用了局部变量num”,如图5-17所示。
图5-17 错误信息
global和nonlocal关键字
4.2
2. nonlocal关键字
【例5-16】 分析以下程序的运行结果。
【参考代码】
def outer():
num = 1
def inner():
nonlocal num #nonlocal关键字声明变量
num = 2
print('inner函数中num的值:',num)
inner()
print('outer函数中num的值:',num)
outer()
【运行结果】 程序运行结果如图5-18所示。
图5-18 例5-16程序运行结果
global和nonlocal关键字
4.2
2. nonlocal关键字
【程序说明】 在inner()函数中使用了nonlocal关键字声明num,即inner()函数中的num就是outer()函数中的num。因此,将num修改为2后,inner()函数和outer()函数中的输出都是2。
如果没有“nonlocal num”这条语句,那么在inner()函数中的num就是局部变量,其值为2,在outer()函数中的num值为1,运行结果如图5-19所示。
图5-19 没有“nonlocal num”语句的运行结果
PART 05
隐藏名字的积木
隐藏名字的积木
5
关键字lambda用于定义一种特殊的函数——匿名函数,又称lambda函数。匿名函数并非没有名字,而是将函数名作为函数结果返回,其基本语法格式如下。
函数名 = lambda [参数列表]:表达式
简单地说,lambda函数用于定义简单的、能够在一行内表示的函数,返回一个函数名。例如:
#定义lambda函数,用于计算两个数的和,并将函数名赋给sum
sum = lambda arg1, arg2: arg1 + arg2
#调用sum()函数,输出返回值结果为30
print('两数相加后的值为:', sum(10, 20))
lambda函数常用在临时需要一个类似于函数的功能,但又不想定义函数的场合。例如,作为内置函数sorted()和列表方法sort()的key参数。
隐藏名字的积木
5
【例5-17】 将学生信息(包括学号、姓名和成绩)按成绩升序排序后输出。
【参考代码】
#定义学生信息列表,元素为字典
stu = [{'num': '201801', 'name': '王五', 'score': 89},
{'num': '201802', 'name': '刘军', 'score': 95},
{'num': '201803', 'name': '李梦', 'score': 85}]
stu.sort(key=lambda x: x['score']) #按成绩升序排序
for s in stu:
#输出列表中的元素
print('学号:',s['num'],'姓名:',s['name'],'成绩:',s['score'])
【问题分析】 首先使用字典存储每个学生的信息,再用列表存储多个学生信息。然后使用sort()方法对列表按学生成绩进行升序排序,并使用lambda函数作为参数key的值。
隐藏名字的积木
5
【运行结果】 程序运行结果如图5-20所示。
图5-20 例5-17程序运行结果
PART 06
积木盒子
模块的导入
6.1
import 模块名 [as 别名]
使用这种方式导入模块后,调用模块中的函数时须在函数名前加上模块名作为前缀,其语法格式如下。
使用import关键字导入整个模块的基本语法格式如下。
1.导入整个模块
模块名.函数名
因为在多个模块中,可能存在名称相同的函数,此时如果只通过函数名来进行调用,解释器将无法知道到底要调用哪个函数。例如:
print(math.sqrt(4)) #输出4的开方,结果为2.0
当模块名很长时,可为导入的模块设置别名,然后使用“别名.函数名”的方式调用函数。例如:
import random as r #导入random模块,并设置别名为r
print(r.randint(1, 100)) #输出1~100的随机整数,结果可能为20
模块的导入
6.1
from 模块名 import 函数名 [as 别名]
使用这种方式仅导入明确指定的函数,并且可以为导入的函数设置别名。这种导入方式可以减少查询次数,提高访问速度,同时也可以减少代码量。在调用函数时,不需要使用模块名作为前缀。例如:
当只需要用到模块中的某个函数时,可只导入特定的函数,其基本语法格式如下。
2.导入特定的函数
from math import sqrt #只导入math中的指定函数sqrt()
print(sqrt(9)) #输出9的开方,结果为3.0
from random import randint as r #给导入的randint()函数设置别名为r
print(r(1, 10)) #输出1~10的随机整数,结果可能为7
模块的导入
6.1
from 模块名 import *
例如:
使用“*”符号可导入模块中的所有内容(包括函数和常量等),其基本语法格式如下。
3.导入模块中所有内容
from math import * #导入math模块中的所有内容
print(pi) #输出常数π,结果为3.141592653589793
print(log2(8)) #计算并输出以2为底的对数值,结果为3.0
print(sqrt(16)) #计算并输出16的开方,结果为4.0
这种方式可以直接使用模块中的所有函数而不需要再使用模块名作为前缀。但一般并不推荐这样使用,因为这样做会降低代码的可读性,同时会导致命名空间的混乱。
模块的创建
6.2
每个Python文件都可以作为一个模块,模块名就是文件名。例如,现有一个文件“add.py”,其中定义了添加学生信息的函数addStuInfo(),代码如下。
#添加一个学生信息
def addStuInfo(stuInfos):
num = input('请输入新学生的学号:') #提示并获取学生的学号
name = input('请输入新学生的姓名:') #提示并获取学生的姓名
sex = input('请输入新学生的性别(男/女):') #提示并获取学生的性别
newInfo = {} #定义字典
#将学生信息保存在字典中
newInfo['num'] = num
newInfo['name'] = name
newInfo['sex'] = sex
stuInfos.append(newInfo) #将字典添加到列表中
模块的创建
6.2
【例5-18】 调用上述add模块中的addStuInfo()函数,添加3个学生信息并输出。
【参考代码】
import add #导入add模块
stuInfos = [] #创建空列表
for i in range(3): #循环3次
add.addStuInfo(stuInfos) #调用addStuInfo()函数,添加学生信息
for info in stuInfos: #遍历列表
print(info) #输出列表的元素
模块的创建
6.2
【运行结果】 程序运行结果如图5-21所示。
图5-21 例5-18程序运行结果
__name__属性
6.3
在实际开发过程中,开发人员为了测试模块的效果,会自行在模块中添加测试信息。例如,在“add.py”文件中添加测试代码如下。
#添加一个学生信息
def addStuInfo(stuInfos):
num = input('请输入新学生的学号:') #提示并获取学生的学号
name = input('请输入新学生的姓名:') #提示并获取学生的姓名
sex = input('请输入新学生的性别(男/女):') #提示并获取学生的性别
newInfo = {} #定义字典
__name__属性
6.3
此时,如果在其他程序中导入此模块,测试代码会在导入时自动运行。重新运行例5-18程序,运行结果如图5-22所示。
#将学生信息保存在字典中
newInfo['num'] = num
newInfo['name'] = name
newInfo['sex'] = sex
stuInfos.append(newInfo) #将字典添加到列表中
#测试代码
stuInfos = [] #创建空列表
addStuInfo(stuInfos) #调用addStuInfo()函数
print('测试信息', stuInfos) #输出测试信息
__name__属性
6.3
图5-22 “add.py”文件中添加测试代码后例5-18程序运行结果
__name__属性
6.3
【程序说明】 从上述结果可以看出,“add.py”中的测试代码也运行了。但这并不合理,测试代码应只在单独执行“add.py”文件时执行,而不应在其他文件中作为模块导入时执行。
为解决这个问题,Python提供了一个__name__属性。通过__name__属性可以识别程序的使用方式:当作为模块导入时,则其__name__属性的值被自动设置为模块名;如果作为程序直接运行,则其__name__属性被自动设置为字符串“__main__”。因此,如果想要在模块被导入时,模块中的某一代码块不执行,可以通过判断__name__属性的值来实现。
例如,如果将“add.py”作为程序直接运行时,执行测试代码,而“add.py”作为模块导入时,不执行测试代码,可将“add.py”文件中的测试代码修改如下。
#测试代码
if __name__ == '__main__': #识别当前的运行方式
stuInfos = [] #创建空列表
addStuInfo(stuInfos) #调用addStuInfo()函数
print('测试信息', stuInfos) #输出测试信息
__name__属性
6.3
再次运行例5-18程序,可以看到“add.py”文件中的测试代码没有执行,程序运行结果如图5-23所示。
图5-23 “add.py”文件中添加__name__属性后例5-18程序运行结果
包
6.4
为了更好地组织模块,通常会将多个模块放在一个目录中,该目录称为包。且该目录下必须存在__init__.py文件(文件内容可以为空)。例如,有下面包结构。
package_1
|—— __init__.py
|—— module_1.py
|—— module_2.py
|—— module_3.py
main.py
包
6.4
此时,如果“main.py”想要调用package_1包中模块module_1中的fun()函数,可以用下面代码实现。
import package_1.module_1 #导入模块
package_1.module_1.fun() #调用函数
也可以用下面代码实现。
from package_1 import module_1 #导入模块
module_1.fun() #调用函数
感谢观看
展开更多......
收起↑