函数
函数,就是一系列指令语句所组成,它的目的有两个。
-
当我们在设计一个大型程序时, 若是能将这个程序依功能, 将其分割成较小的功能, 然后依这些较小功能要求撰写函数程序, 如此, 不仅使程序简单化, 最后程序侦错也变得容易。 另外,撰写大型程序时应该是团队合作, 每一个人负责一个小功能, 可以缩短程序开发的时间。
-
在一个程序中, 也许会发生某些指令被重复书写在许多不同的地方, 若是我们能将这些重复的指令撰写成一个函数, 需要用时再加以调用, 如此, 不仅减少编辑程序的时间, 更可使程序精简、 清晰、 明了。
函数调用的基本流程图
1.1Python函数的基本观念
1.1.1 函数的定义
函数的语法格式如下:
def 函数名称(参数值1[,参数值2,...])
"""函数批注"""
程序代码区块
return [返回值1,返回值2,...]
-
函数名称 名称必须是唯一的,程序未来可以调用引用。(故Python中没有函数重载)
-
参数值 是可有可无的, 完全视函数设计需要, 可以接收调用函数传来的变量, 各参数值之间是用逗号“,” 隔开。
-
函数批注 这是可有可无的, 不过如果是参与大型程序设计计划, 当负责一个小程序时, 建议所设计的函数需要加上批注, 除了自己需要也是方便他人阅读。 主要是注明此函数的功能,由于可能有多行批注所以可以用3个双引号(或单引号)包夹。 许多英文Python资料称此为docstring(document string 的缩写)。
-
return[返回值1,返回值2 ,…] 不论是return或接续右边的返回值皆是可有可无, 如果有返回多个数据彼此需以逗号","隔开。
1.1.2无参数无返回值的函数
创建函数
def greeting():
"""第一个Python函数设计"""
print("Python欢迎你")
print("祝福学习顺利")
print("谢谢")
# 以下的代码程序也可称为主程序
greeting()
greeting()
greeting()
greeting()
Python欢迎你
祝福学习顺利
谢谢
Python欢迎你
祝福学习顺利
谢谢
Python欢迎你
祝福学习顺利
谢谢
Python欢迎你
祝福学习顺利
谢谢
不使用函数
print("Python欢迎你")
print("祝福学习顺利")
print("谢谢")
print("Python欢迎你")
print("祝福学习顺利")
print("谢谢")
print("Python欢迎你")
print("祝福学习顺利")
print("谢谢")
print("Python欢迎你")
print("祝福学习顺利")
print("谢谢")
上述程序虽然也可以完成工作, 但是可以发现重复的语句太多了, 这不是一个好的设计。 同时如果要将“Python欢迎你” 改成“Python欢迎你们” , 程序必须修改5次相同的语句。 这就是函数的好处。
1.2函数参数设计
1.2.1 传递一个参数
函数内有参数的应用
def greeting(name):
"""Python函数需传递名字name"""
print("Hi,", name, 'Good Morning!')
#print("Hi," + name +'Good Morning!') 可以用这行代码代替
greeting('LiMing')
Hi, LiMing Good Morning!
1.2.2 多个参数的传递
当所设计的函数需要传递多个参数, 调用此函数时就需要特别留意传递参数的位置需要正确,最后才可以获得正确的结果。 最常见的传递参数是数值或字符串数据, 有时也会需要传递列表、 元组或字典。
设计减法的函数subtract(),第一个参数会减去第二个参数, 然后列出执行结果。
def subtract(x1, x2):
"""减法设计"""
result = x1 - x2
print(result)
print("本程序会执行 a-b 的运算")
a = int(input("a = "))
b = int(input("b = "))
print("a - b = ", end='')
subtract(a, b)
本程序会执行 a-b 的运算
a = 5
b = 4
a - b = 1
上述函数功能是减法运算, 所以需要传递2个参数, 然后执行第一个数值减去第2个数值。 调用这类的函数时, 就必须留意参数的位置, 否则会有错误信息产生。
这也是一个需传递2个参数的实例, 第一个是兴趣(interest),第二个是主题(subject) 。
def interest(interest_type, subject):
"""显示兴趣和主题"""
print("我的兴趣是 " + interest_type)
print("在 " + interest_type + "中,最喜欢的是 " + subject)
print()
interest('旅游', '敦煌')
interest('程序设计', 'Python')
我的兴趣是 旅游
在 旅游中,最喜欢的是 敦煌
我的兴趣是 程序设计
在 程序设计中,最喜欢的是 Python
第8行调用interest ()
时, '旅游’会传给interest_type
、'敦煌’会传给subject
1.2.3 关键词参数 参数名称 = 值
关键词参数(keyword arguments)是指调用函数时, 参数是用参数名称=值配对方式呈
现。 Python也允许在调用需传递多个参数的函数时, 直接将参数名称=值用配对方式传送, 这个时候参数的位置就不重要了 。
用参数名称=值配对方式传送。
def interest(interest_type, subject):
"""显示兴趣和主题"""
print("我的兴趣是 " + interest_type)
print("在 " + interest_type + "中,最喜欢的是 " + subject)
print()
interest(interest_type='旅游', subject='敦煌')
interest(subject='Python', interest_type='程序设计')
我的兴趣是 旅游
在 旅游中,最喜欢的是 敦煌
我的兴趣是 程序设计
在 程序设计中,最喜欢的是 Python
“interest_type=‘旅游’, 当调用函数用配对方式传送参数时, 即使参数位置错误, 程序执行结果也会相同, 因为在调用时已经明确指出所传递的值是要给哪一个参数了 。
1.2.4 参数默认值的处理
在设计函数时也可以给参数默认值, 如果调用的这个函数没有给参数值, 函数的默认值将派上用场。 函数设计时含有默认值的参数, 必须放置在参数列的最右边。
subject的默认值设为“敦煌”。
def interest(interest_type, subject='敦煌'):
"""显示兴趣和主题"""
print("我的兴趣是 " + interest_type)
print("在 " + interest_type + "中,最喜欢的是 " + subject)
print()
interest('旅游')
interest(interest_type='旅游')
interest('旅游', '张家界')
interest(interest_type='旅游', subject='张家界')
interest(subject='张家界', interest_type='旅游')
我的兴趣是 旅游
在 旅游中,最喜欢的是 敦煌
我的兴趣是 旅游
在 旅游中,最喜欢的是 敦煌
我的兴趣是 旅游
在 旅游中,最喜欢的是 张家界
我的兴趣是 旅游
在 旅游中,最喜欢的是 张家界
我的兴趣是 旅游
在 旅游中,最喜欢的是 张家界
默认参数如果不传入,则为默认的数据;如果传入,则将默认参数覆盖。
1.3 函数的返回值
Python中有许多内置的函数,有时候会返回一些有意义的数据,例如:len()
返回元素数量。 有些没有返回值, 此时Python会自动返回None,例如: clear()
。
1.3.1 返回None
在设计函数时,如果没有“return [返回值]”
,Python在直译时会自动返回处理成“return None”
,相当于返回None。在一些程序语言, 例如, C语言这个None
就是NULL
, None
在Python中独立成为一个数据类型NoneType
。
Python返回greeting()函数的数据是否是None,同时列出返回值的数据类型。
def greeting(name):
"""Python函数需传递名字name"""
print("Hi, ", name, "Good Morning!")
ret_value = greeting('LiMing')
print('greeting()传回值 = ', ret_value)
print(ret_value, '的 type =', type(ret_value))
Hi, LiMing Good Morning!
greeting()传回值 = None
None 的 type = <class 'NoneType'>
函数末端增加return
def greeting(name):
"""Python函数需传递名字name"""
print("Hi, ", name, "Good Morning!")
return # Python将自动传回None
ret_value = greeting('LiMing')
print('greeting()传回值 = ', ret_value)
print(ret_value, '的 type =', type(ret_value))
1.3.2 简单返回数值数据
参数具有返回值功能, 将可以大大增加程序的可读性, 返回的基本方式 如下
return result # result就是返回的值
利用函数的返回值,重新设计减法运算。
def subtract(x1, x2):
"""减法设计"""
result = x1 - x2
return result # 返回减法结果
print("本程序会执行 a - b 的运算")
a = int(input("a = "))
b = int(input("b = "))
print("a - b = ", subtract(a, b)) # 输出a-b字符串的结果
本程序会执行 a - b 的运算
a = 5
b = 2
a - b = 3
一个程序常常是由许多函数所组成, 下列是程序含2个函数的应用。
设计加法和减法器
def subtract(x1, x2):
"""减法设计"""
return x1 - x2 # 返回减法结果
def addition(x1, x2):
"""加法设计"""
return x1 + x2 # 返回加法结果
print("请输入运算")
print("1:加法")
print("2:减法")
op = int(input("输入1/2: "))
a = int(input("a = "))
b = int(input("b = "))
if op == 1:
print("a + b = ", addition(a, b)) # 输出a+b字符串和结果
elif op == 2:
print("a - b = ", subtract(a, b)) # 输出a-b字符串和结果
else:
print("运算方法输入错误")
请输入运算
1:加法
2:减法
输入1/2: 1
a = 5
b = 6
a + b = 11
1.3.3 返回多个数据的应用
使用return返回函数数据时, 也允许返回多个数据, 各个数据间只要以逗号隔开即可。
请输入两个数据,此函数将返回加法、减法、乘法、除法的执行结果。
def mutifuncion(x1, x2):
"""加,间,乘,除四则运算"""
addresult = x1 + x2
subresult = x1 - x2
mulresult = x1 * x2
divresult = x1 / x2
return addresult, subresult, mulresult, divresult
x1 = x2 = 10
add, sub, mul, div = mutifuncion(x1, x2)
print("加法运算结果 = ", add)
print("减法运算结果 = ", sub)
print("乘法运算结果 = ", mul)
print("除法运算结果 = ", div)
加法运算结果 = 20
减法运算结果 = 0
乘法运算结果 = 100
除法运算结果 = 1.0
1.3.4 简单返回字符串数据
一般中文姓名是3个字, 笔者将中文姓名拆解为第一个字是姓lastname
,第二个字是中间名middlename
,第三个字是名firstnanie
。 这个程序内有一个函数guest info(),参数意义分别是名firstnanie
、 中间名middlename
和姓lastname
,以及性别gender组织起来, 同时加上问候语返回。
def guest_info(firstname, middlename, lastname, gender):
"""整合客户名字数据"""
if gender == 'M':
welcome = lastname + middlename + firstname + '先生欢迎你'
else:
welcome = lastname + middlename + firstname + '小姐欢迎你'
return welcome
info1 = guest_info('宇', '星', '洪', 'M')
info2 = guest_info('雨', '冰', '洪', 'F')
print(info1)
print(info2)
洪星宇先生欢迎你
洪冰雨小姐欢迎你
1.3.5 再谈参数默认值
虽然大多数国人的名字是由3个字所组成, 但是偶尔也会遇上2个字的状况, 例如, 著名影
星刘涛。 其实外国人的名字中, 有些人也是只有2个字, 因为没有中间名middlename
。 故可以在函数设计时将middlename
默认为空字符串, 这样就可以处理没有中间名的问题。
会将middlename
默认为空字符串, 这样就可以处理没有中间名middlename
的问题, 请留意函数设计时需将此参数预设放在最右边,
def guest_info(firstname, lastname, gender, middlename=''):
"""整合客户名字数据"""
if gender == 'M':
welcome = lastname + middlename + firstname + '先生欢迎你'
else:
welcome = lastname + middlename + firstname + '小姐欢迎你'
return welcome
info1 = guest_info('涛', '刘', 'M')
info2 = guest_info('雨', '冰', 'F', '洪')
print(info1)
print(info2)
刘涛先生欢迎你
冰洪雨小姐欢迎你
调用guest_info()函数时只有3个参数, middlename
就会使用默认的空字符串;
调用guest_info()函数时有4个参数, middlename
就会使用调用函数时所设的字符串’冰’;
1.3.6 函数返回字典数据
函数除了可以返回数值或字符串数据外, 也可以返回比较复杂的数据, 例如, 字典或列表等。
这个程序会调用build_vip
函数, 在调用时会输入VIP_ID
编号和Name
姓名数据, 函数将返回所建立的字典数据。
def build_vip(id, name):
"""建立VIP信息"""
vip_dict = {'VIP_ID': id, 'Name': name}
return vip_dict
member = build_vip('101', 'LiMing')
print(member)
{'VIP_ID': '101', 'Name': 'LiMing'}
上述字典数据只是一个简单的应用, 在真正的企业建立VIP数据的案例中, 可能还需要性别、电话号码、 年龄、 电子邮件、 地址等信息。 在建立VIP数据过程, 也许有些人会乐意提供手机号码, 有些人不乐意提供, 函数设计时我们也可以将Tel电话号码默认为空字符串, 但是如果有提供电话号码时, 程序也可以将它纳入字典内容。
增加电话号码, 调用时若没有提供电话号码则字典不含此字段, 调用时若有提供电话号码则字典含此字段。
def build_vip(id, name, tel=''):
"""建立VIP信息"""
vip_dict = {'VIP_ID': id, 'Name': name}
if tel:
vip_dict['Tel'] = tel
return vip_dict
member1 = build_vip('101', 'Nelson')
member2 = build_vip('102', 'Henry', '0952222333')
print(member1)
print(member2)
{'VIP_ID': '101', 'Name': 'Nelson'}
{'VIP_ID': '102', 'Name': 'Henry', 'Tel': '0952222333'}
程序调用build_vip()
函数时, 由于有提供电话号码字段, 所以上述程序会得到述叙述的tel
是True,
所以在会将此字段增加到字典中 。
1.3.7 将循环应用在建立VIP会员字典
我们可以将循环的观念应用在VIP会员字典的建立。
这个程序在执行时基本上是用无限循环的观念, 但是当一个数据建立完成时, 会询问是否继续, 如果输入非‘y’字符, 程序将执行结束。
def build_vip(id, name, tel=''):
"""建立VIP信息"""
vip_dict = {'VIP_ID': id, 'Name': name}
if tel:
vip_dict['Tel'] = tel
return vip_dict
while True:
print("建立VIP信息系统")
idnum = input("请输入ID:")
name = input('请输入姓名:')
tel = input("请输入电话号码:") # 按Enter直接终止,不建立此字段
member = build_vip(idnum, name, tel) # 建立字典
print(member, '\n')
repeat = input("是否继续(y/n)?输入非y字符可结束系统:")
if repeat != 'y':
break
print("欢迎下次再使用")
在上述输入第2个数据时, 在电话号码字段没有输入直接单击Enter键, 这个动作相当于不做输入, 此时将造成可以省略此字段 。
1.4 调用函数时参数是列表
1.4.1 基本传递列表参数的应用
在调用函数时, 也可以将列表(此列表可以是由数值、 字符串或字典所组成)当参数传递给函数, 然后函数可以遍历列表内容, 然后执行更进一步的运作。
传递列表给product_msg()函数, 函数会遍历列表, 然后列出一封产品发表会的信件。
def product_msg(customers):
str1 = '亲爱的'
str2 = '本公司将在2020年12月20日北京举行产品发表会'
str3 = '总经理:深石敬上'
for customer in customers:
msg = str1 + customer + '\n' + str2 + '\n' + str3
print(msg, '\n')
members = ['Damon', 'Peter', 'Mary']
product_msg(members)
亲爱的Damon
本公司将在2020年12月20日北京举行产品发表会
总经理:深石敬上
亲爱的Peter
本公司将在2020年12月20日北京举行产品发表会
总经理:深石敬上
亲爱的Mary
本公司将在2020年12月20日北京举行产品发表会
总经理:深石敬上
1.4.2 在函数内修订列表的内容
Python允许在函数内直接修订列表的内容, 同时列表经过修正后, 主程序的列表也将随之永久性更改结果。
设计一个麦当劳的点餐系统, 顾客在麦当劳点餐时, 可以将所点的餐点放入unserved列表, 服务完成后将已服务餐点放入served列表。
def kitchen(unserved, served):
"""将未服务的餐点转为已经服务"""
print("厨房处理顾客所点的餐点")
while unserved:
current_meal = unserved.pop()
# 模拟出餐点过程
print("菜单: ", current_meal)
# 将已出餐点转入已经服务列表
served.append(current_meal)
def show_unserve_meal(unserved):
"""显示尚未出餐的餐点"""
print("===下列是尚未服务的餐点===")
if not unserved:
print("***没有餐点***")
else:
for unserved_meal in unserved:
print(unserved_meal)
def show_served_meal(severd):
"""显示已经服务的餐点"""
print("===下列是已经服务的餐点===")
if not severd:
print("***没有餐点***")
else:
for severd_meal in severd:
print(severd_meal)
unserved = ['大麦克', '劲辣鸡腿堡', '麦克鸡块']
served = []
# 列出餐厅处理前的点餐内容
show_unserve_meal(unserved)
show_served_meal(served)
# 餐厅服务过程
kitchen(unserved, served)
print("\n", "===厨房处理结束===", "\n")
# 列出餐厅处理后的点餐内容
show_unserve_meal(unserved)
show_served_meal(served)
===下列是尚未服务的餐点===
大麦克
劲辣鸡腿堡
麦克鸡块
===下列是已经服务的餐点===
***没有餐点***
厨房处理顾客所点的餐点
菜单: 麦克鸡块
菜单: 劲辣鸡腿堡
菜单: 大麦克
===厨房处理结束===
===下列是尚未服务的餐点===
***没有餐点***
===下列是已经服务的餐点===
麦克鸡块
劲辣鸡腿堡
大麦克
对于上述程序而言, 读者可能会好奇, 主程序部分与函数部分是使用相同的列表变量served与unserved,所以经过第36行调用kitchen()后造成列表内容的改变, 是否设计这类欲更改列表内容的程序, 函数与主程序的变量名称一定要相同? 答案是否定的。 其实这牵涉到全局变量(global variable)与局部变量(local variable)的观念。
当传递列表给函数时,即使函数内的列表与主程序列表是不同的名称,但是函数列表中的值和主程序列表的值是指向相同的内存位置,所以在函数更改列表内容时主程序列表的内容也随着更改。
1.4.3 使用副本传递列表
有时候设计餐厅系统时, 可能想要保存餐点内容, 但是经过先前程序设计可以发现,保存未服务餐点的列表已经变为空列表了, 为了避免这样的情形发生, 可以在调用kitchen()函数时传递副本列表, 处理方式如下:
kitchen(order_list[:], served_list) # 传递副本列表
如果传递为kitchen(order_list[:],served_list)
,order_list不会受到函数的影响而发生变化。
如果传递为kitchen(order_list, served_list),
order_list会受到函数的影响而发生变化。
def kitchen(unserved, served):
"""将未服务的餐点转为已经服务"""
print("厨房处理顾客所点的餐点")
while unserved:
current_meal = unserved.pop()
# 模拟出餐点过程
print("菜单: ", current_meal)
# 将已出餐点转入已经服务列表
served.append(current_meal)
def show_unserve_meal(unserved):
"""显示尚未出餐的餐点"""
print("===下列是尚未服务的餐点===")
if not unserved:
print("***没有餐点***")
else:
for unserved_meal in unserved:
print(unserved_meal)
def show_served_meal(severd):
"""显示已经服务的餐点"""
print("===下列是已经服务的餐点===")
if not severd:
print("***没有餐点***")
else:
for severd_meal in severd:
print(severd_meal)
order_list = ['大麦克', '劲辣鸡腿堡', '麦克鸡块']
served = []
# 列出餐厅处理前的点餐内容
show_unserve_meal(order_list)
show_served_meal(served)
# 餐厅服务过程
kitchen(order_list[:], served) # 对于kitchen函数传入
print("\n", "===厨房处理结束===", "\n")
# 列出餐厅处理后的点餐内容
show_unserve_meal(order_list)
show_served_meal(served)
===下列是尚未服务的餐点===
大麦克
劲辣鸡腿堡
麦克鸡块
===下列是已经服务的餐点===
***没有餐点***
厨房处理顾客所点的餐点
菜单: 麦克鸡块
菜单: 劲辣鸡腿堡
菜单: 大麦克
===厨房处理结束===
===下列是尚未服务的餐点===
大麦克 # 未被消除
劲辣鸡腿堡
麦克鸡块
===下列是已经服务的餐点===
麦克鸡块
劲辣鸡腿堡
大麦克
执行结果可以发现, 原先存储点餐的。 idealist列表经过kitchen。函数后, 此列表的内容没有改变
1.5 传递任意数量的参数
1.5.1 基本传递处理任意数量的参数
在设计Python的函数时, 有时候可能会碰上不知道会有多少个参数会传递到这个函数, 此时可以用下列方式设计。
建立一个冰淇淋的配料程序, 一般冰淇淋可以在上面加上配料, 这个程序在调用制作冰淇淋函数make_icecieam()
时, 可以传递0到多个配料, 然后make_icecream()
函数会将配料结果的冰淇淋列出来。
def make_icecream(*toppings): # 加上“*”符号的参数代表可以有1到多个参数将传递到这个函数内
# 列出制作冰激凌的配料
print("这个冰淇凌所加配料如下")
for topping in toppings:
print("---", topping)
make_icecream('草莓酱')
make_icecream('草莓酱', '葡萄干', '巧克力碎片')
这个冰淇凌所加配料如下
--- 草莓酱
这个冰淇凌所加配料如下
--- 草莓酱
--- 葡萄干
--- 巧克力碎片
1.5.2 设计含有一般参数与任意数量参数的函数
程序设计时有时会遇上需要传递一般参数与任意数量参数, 碰上这类状况, 任意数量的参数必须放在最右边。
传递参数时第一个参数是冰淇淋的种类, 然后才是不同数量的冰淇淋的配料
def make_icecream(icecream_type, *toppings):
# 列出制作冰淇淋的配料
print("这个 ", icecream_type, " 冰淇淋所加配料如下")
for topping in toppings:
print("--- ", topping)
make_icecream('香草', '草莓酱')
make_icecream('芒果', '草莓酱', '葡萄干', '巧克力碎片')
这个 香草 冰淇淋所加配料如下
--- 草莓酱
这个 芒果 冰淇淋所加配料如下
--- 草莓酱
--- 葡萄干
--- 巧克力碎片
1.5.3 设计含有一般参数与任意数量的关键词参数
设计含任意数量关键词参数的函数。
这个程序基本上是用build_dict()
函数建立一个球员的字典数据, 主程序会传入一般参数与任意数量的关键词参数, 最后可以列出执行结果。
def build_dict(name, age, **player):
# 建立NBA球员的字典数据
info = {} # 建立空字典
info['Name'] = name
info['Age'] = age
for key, value in player.items():
info[key] = value
return info # 返回所建的字典
player_dict = build_dict('James', '32', City='Cleveland', State='Ohio')
print(player_dict)
{'Name': 'James', 'Age': '32', 'City': 'Cleveland', 'State': 'Ohio'}
1.6 递归式函数设计recursive
一个函数可以调用其他函数也可以调用自己, 其中调用本身的动作称递归式(recursive)调用,递归式调用有下列特点:
- 每次调用自己时,都会是范围越来越小
- 必须要有一个终止的条件来结束递归函数
递归函数可以使程序变得很简洁, 但是设计这类程序一不小心就很容易掉入无限循环的陷阱,所以使用这类函数时一定要特别小心。 递归函数最常见的应用是处理正整数的阶乘(factorial), 一个正整数的阶乘是所有小于以及等于该数的正整数的积, 同时如果正整数是0则阶乘为1,依照观念正整数是1时阶乘也是1,此阶乘数字的表示法为n!。
实例1:n = 3, 下列是阶乘数的计算方式
n ! = 1 * 2 * 3 结果是6
def factorial(n):
# 计算n的阶乘, n必须是正整数
if n == 0:
return 1
else:
return (n * factorial(n - 1))
a = factorial(3)
print(a)
6
1.7 局部变量与全局变量
在设计函数时, 另一个重点是适当地使用变量名称, 某个变量只有在该函数内使用, 影响范围限定在这个函数内, 这个变量称**局部变量(local vanable)
。如果某个变量的影响范围是在整个程序**,则这个变量称**全局变量(global variable)
**Python程序在调用函数时会建立一个内存工作区间, 在这个内存工作区间可以处理属于这个函数的变量, 当函数工作结束, 返回原先调用程序时, 这个内存工作区间就被收回, 原先存在的变量也将被销毁, 这也是为何局部变量的影响范围只限定在所属的函数内。
对于全局变量而言, 一般是在主程序内建立, 程序在执行时, 不仅主程序可以引用, 所有属于这个程序的函数也可以引用, 所以它的影响范围是整个程序。
1.7.1 全局变量可以在所有函数使用
一般在主程序内建立的变量称全局变量, 这个变量程序内与本程序的所有函数皆可以引用。
这个程序会设定一个全局变量, 然后函数也可以调用引用。
def printmsg():
# 函数本身没有定义变量,只有执行打印全局变量功能
print("函数打印:", msg) # 打印全局变量
msg = 'Global Variable' # 设定全局变量
print("主程序打印:", msg) # 打印全局变量
printmsg()
主程序打印: Global Variable
函数打印: Global Variable
1.7.2 局部变量与全局变量使用相同的名称
在程序设计时建议全局变量与函数内的局部变量不要使用相同的名称, 因为很容易造成混淆。如果全局变量与函数内的局部变量使用相同的名称, Python会将相同名称的区域与全局变量视为不同的变量, 在局部变量所在的函数是使用局部变量内容, 其他区域则是使用全局变量的内容
局部变量与全局变量定义了相同的变量msg,但是内容不相同。 然后执行打印, 可以发现在函数与主程序所打印的内容有不同的结果
def printmsg():
# 函数本身有定义变量,只有执行打印局部变量功能
msg = 'Local Varable' # 设定局部变量
print("函数打印:", msg) # 打印全局变量
msg = 'Global Variable' # 设定全局变量
print("主程序打印:", msg) # 打印全局变量
printmsg()
主程序打印: Global Variable
函数打印: Local Varable
1.7.3 程序设计需注意事项
一般程序设计时有关使用局部变量需注意下列事项, 否则程序会有错误产生。
- 局部变量内容无法再其它函数引用。
- 局部变量内容无法再主程序引用。
局部变量在其他函数引用, 造成程序错误的应用。
def defmsg():
msg = 'pringmsg variable'
def printmsg():
print(msg) # 打印defmsg()函数定义的局部变量
printmsg()
NameError: name 'msg' is not defined
上述程序的错误原因主要是defmsg()
函数内没有定义msg
变量, 所以产生程序错误。
局部变量在主程序引用产生错误的实例。
def defmsg():
msg = 'pringmsg variable'
print(msg) # 主程序打印局部变量产生错误
NameError: name 'msg' is not defined
1.8 匿名函数 lambda
所谓的匿名函数(anonymous function)是指一个没有名称的函数, Python是使用def定义一般函数, 匿名函数则是使用lambda来定义, 有的人称之为lambda表达式, 也可以将匿名函数称lambda函数。 通常会将匿名函数与Python的内置函数filter()、 map()等共同使用, 此时匿名函数将只是这些函数的参数。
1.8.1 匿名函数lambda的语法
匿名函数最大特色是可以有许多的参数, 但是只能有一个程序码表达式, 然后可以将执行结果返回。
lambda arg1[,arg2,...,argn]:expression # arg1是参数,可以有多个参数
这是单一参数的匿名函数应用, 可以返回平方值。
# 定义lambda函数
square = lambda x: x ** 2
# 输出平方值
print(square(10))
100
含2个参数的匿名函数应用, 可以返回参数的积(相乘的结果) 。
# 定义lambda函数
product = lambda x, y: x * y
# 输出两数的积
print(product(5, 10))
50
1.8.2 匿名函数使用与filter( )
匿名函数一般是用在不需要函数名称的场合, 例如, 一些高阶函数(higher-order function)的参数可能是函数, 这时就很适合使用匿名函数, 同时让程序变得更简洁。 有一个内置函数filter(),它的语法格式如下:
filter(function, iterable)
上述函数将依次对iterable
(可以重复执行, 例如, 字符串string
、列表list
或元组tuple
)的元素(item
)放入function(item
)内, 然后将function
()函数执行结果是True
的元素(item)组成新的筛选对象(filter object)返回。
参数:
接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回True
或False
,最后将返回True
的元素放到新列表中。
function
判断函数。iterable
可迭代对象。
返回值:
filter函数
在Python3
中返回一个惰性计算的filter对象
或迭代器
。我们不能通过index
访问filter对象
的元素,也不能使用len()
得到它的长度。
使用传统函数定义方式将列表元素内容是奇数的元素筛选出来。
def oddfn(x):
return x if (x % 2 == 1) else None
mylist = [5, 10, 15, 20, 25, 30]
filter_object = filter(oddfn, mylist) # 传回filter object
print(filter_object)
# 法一
# 输出奇数列表
print("奇数列表: ", [item for item in filter_object])
# 法二
# oddlist = [item for item in filter_object]
# print("奇数列表:", oddlist)
# 两者不能同时存在,迭代对象只能用来迭代一次
1.8.3 使用匿名函数使用与map()
有一个内置函数map(),它的语法格式如下:
map(function, iterable)
上述函数将依次对iterable
(可以重复执行, 例如, 字符串string
、列表list
或元组tuple
)的元素(item
)放入funtion
(item)内,然后将function()
函数执行结果组成新的筛选对象(filter object
)返回。
使用匿名函数对列表元素执行计算平方。
mylist = [5, 10, 15, 20, 25, 30]
squarelist = list(map(lambda x: x ** 2, mylist))
# 输出列表元素的平方值
print("列表的平方值:", squarelist)
列表的平方值: [25, 100, 225, 400, 625, 900]
1.9 pass与函数
当我们在设计大型程序时, 可能会先规划各个函数的功能, 然后逐一完成各个函数设计, 但是在程序完成前我们可以先将尚未完成的函数内容放上pass。
将pass应用在函数设计。
def fun(arg):
pass
1.10 type关键字应用在函数
输出函数与匿名函数的数据类型。
def fun(arg):
pass
print("列出fun的type类型 : ", type(fun))
print("列出lambda的type类型 :", type(lambda x: x))
print("列出内置函数abs的type类型:", type(abs))
列出fun的type类型 : <class 'function'>
列出lambda的type类型 : <class 'function'>
列出内置函数abs的type类型: <class 'builtin_function_or_method'>
两者不能同时存在,迭代对象只能用来迭代一次
### 1.8.3 使用匿名函数使用与map()
有一个内置函数map(),它的语法格式如下:
```python
map(function, iterable)
上述函数将依次对iterable
(可以重复执行, 例如, 字符串string
、列表list
或元组tuple
)的元素(item
)放入funtion
(item)内,然后将function()
函数执行结果组成新的筛选对象(filter object
)返回。
使用匿名函数对列表元素执行计算平方。
mylist = [5, 10, 15, 20, 25, 30]
squarelist = list(map(lambda x: x ** 2, mylist))
# 输出列表元素的平方值
print("列表的平方值:", squarelist)
列表的平方值: [25, 100, 225, 400, 625, 900]
1.9 pass与函数
当我们在设计大型程序时, 可能会先规划各个函数的功能, 然后逐一完成各个函数设计, 但是在程序完成前我们可以先将尚未完成的函数内容放上pass。
将pass应用在函数设计。
def fun(arg):
pass
1.10 type关键字应用在函数
输出函数与匿名函数的数据类型。
def fun(arg):
pass
print("列出fun的type类型 : ", type(fun))
print("列出lambda的type类型 :", type(lambda x: x))
print("列出内置函数abs的type类型:", type(abs))
列出fun的type类型 : <class 'function'>
列出lambda的type类型 : <class 'function'>
列出内置函数abs的type类型: <class 'builtin_function_or_method'>