函数
通过将一段有规律的,重复的代码定义为函数,来达到一次编写,多次调用的目的。
使用函数可以提高代码的重复利用率。
你可以定义一个由自己想要功能的函数,以下是简单的规则:
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
函数内容以冒号起始,并且缩进。
return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
创建函数:
创建函数也叫定义函数。可以理解为创建一个具有某种用途的工具。使用def关键字实现。
语法格式: def functionname(parameterlist): 实例:def math(x)
['''conments'''] y = x + 5
[functionname] return y
def 函数名('参数列表'): a = math(2)
函数体 print(a)#(或者:print(math(2))
return语句 输出:7
# funtionname: 函数名称,在调用函数时使用。
# parameterlist: 可选参数,用于指定向函数中传递的参数。如果有多个参数,各参数间使用逗号","分隔。如果不指定,则表示该函数没有参数,在调用时也不指定参数。
注意:即使函数没有参数,也必须保留一对空的"()"。否则将报错。
# conments: 可选参数,表示函数指定注释,注释内容通常是说明该函数的功能,要传递的参数的作用等,可以为用户提供友好提示和帮助内容。
说明:在定义函数时,如果指定了"conments"参数,那么在调用函数时,输入函数名称及左侧的小括号时,就会显示该函数的帮助信息。
注意:如果在输入函数名和左侧括号后,没有显示友好提示,那么检查函数本身是否有误,可以在未调用时先执行一遍代码。
functionname:可选参数,用于指定函数体,即该函数被调用后,要执行的功能代码,如果函数有返回值,可以使用return语句返回。
注意:函数体"functionname"和注释"conments"相对于def关键字必须保持一定的缩进。
1. 名字最好能体现函数的功能,一般用小写字母和单下划线、数字等组合#
2. 不可与内置函数重名(内置函数不需要定义即可直接使用)
def math(x): # 参数:根据函数功能,括号里可以有多个参数,也可以不带参数,命名规则与函数名相同
# 规范:括号是英文括号,后面的冒号不能丢
y = x + 5 # 函数体:函数的执行过程,体现函数功能的语句,要缩进,一般是四个空格
return y # return语句:后面可以接多种数据类型,如果函数不需要返回值的话,可以省略
调用函数
调用函数也就是执行函数。如果把创建的函数理解为创建一个具有某种功能,用途的工具,那么调用函数就相当于使用工具。
语法格式: functionname([parametersvalue])
# functionname: 函数名称,要调用的函数名称必须是已经创建好的。
# parametervalue: 可选参数,用于指定各个参数的值。如果需要传递多个参数值,则各个参数值之间用","隔开。如果该函数没有参数,则直接写一对括号即可。
例:
def function_tips():
'''功能:每天输出一条励志文字
'''
import datetime # 导入日期时间类
# 定义一个列表
mot = ["坚持下去不是因为我很坚强,而是因为我别无选择",
"含泪播种的人一定能笑着收获",
"做对的事情比把事情做对重要",
"命运给予我们的不是失望之酒,而是机会之杯",
"不要等到明天,明天太遥远,今天就行动",
"求知若饥,虚心若愚",
"成功将属于那些从不说"不可能"的人"]
day=datetime.datetime.now().weekday() # 获取当前星期
print(mot[day]) # 输出每日一帖
#*****************************调用函数***********************************#
function_tips() # 调用函数
参数传递
在调用函数时,主调函数与被调用函数之间有数据传递关系,这就是有参数的函数形式。
形式参数和实际参数。
形式参数:在定义函数时,函数名后面括号中的参数为"形式参数"。
实际参数:在调用一个函数时,函数名后面的括号中的参数为"实际参数",也就是将函数的调用者提供给函数的参数称为实际参数。
例:
def demo(obj): #定义或创建函数,此时的函数参数obj为形式函数。
print(obj)
mot = '没有退路了,前途艰难'
demo(mot) #调用函数,此刻的函数参数mot和list1是实际参数
list1 = ['玲','君']
demo(list1)
输出
没有退路了,前途艰难
['玲', '君']
根据实际参数的类型不同,可以分为将实际参数的值传递给形式参数,和将实际参数的引用传递给形式参数两种情况。
其中,当实际参数为不可变对象时,进行值传递;当实际参数为可变参数时,进行的是引用传递。实际上,值传递和引用传递的基本区别就是,进行值传递后,改变形式参数的值,实际参数的值不变;而进行引用传递后,改变形式参数的值,实际参数的值也一同改变。
函数定义时参数列表中的参数就是形式参数,而函数调用时传递进来的参数就是实际参数。
就像是剧本选角色一样,剧本中的角色就相当于形式参数,而演角色的演员就相当于实际参数。
例:
def fun_bmi(person,height,weight):
'''功能:根据身高和体重计算BMI指数
person:姓名
height:身高,单位:米
weight:体重,单位:千克
'''
print(person + "的身高:" + str(height) + "米 \t 体重:" + str(weight) + "千克")
bmi=weight/(height*height) # 用于计算BMI指数,公式为"体重/身高的平方"
print(person + "的BMI指数为:"+str(bmi)) # 输出BMI指数
# 判断身材是否合理
if bmi<18.5:
print("您的体重过轻 ~@_@~\n")
if bmi>=18.5 and bmi<24.9:
print("正常范围,注意保持 (-_-)\n")
if bmi>=24.9 and bmi<29.9:
print("您的体重过重 ~@_@~\n")
if bmi>=29.9:
print("肥胖 ^@_@^\n")
#*****************************调用函数***********************************#
fun_bmi("路人甲",1.83,60) # 计算路人甲的BMI指数
fun_bmi("路人乙",1.60,50) # 计算路人乙的BMI指数
输出:
路人甲的身高:1.83米 体重:60千克
路人甲的BMI指数为:17.916330735465376
您的体重过轻 ~@_@~
路人乙的身高:1.6米 体重:50千克
路人乙的BMI指数为:19.531249999999996
正常范围,注意保持 (-_-)
位置参数
位置参数也被称为必备参数,是必须按照正确顺序传到函数中,即调用的数量和位置必须和定义时是一样的。
对应参数的位置顺序传递的,所以叫作【位置参数】,当有多个参数的时候,我们就必须按照顺序和数量传递,这也是最常见的参数类型。
数量必须和定义时一致
在调用函数时,指定的实际参数的数量必须与形式参数的数量一致,否则将出现报错。
位置必须和定义时一致
在调用函数时,指定的实际参数的位置必须与形式参数的位置一致,否则将出现报错。
.TypeError异常:实际参数的类型和形式参数的类型不一致,并且在函数,这两种类型还不能正常转换。
.产生的效果与预期不符:在调用函数时,如果指定的实际参数与形式参数的位置不一 致,但是它们的数据类型一致,那么不会出现异常,而是产生结果与预期不符的问题。所以在调用函数时一定要确定好位置,否则产生bug了,还不容易发现。
关键字参数
关键字参数是指使用形式参数的名字来确定输入的参数值。通过这种方式指定实际参数时,不再需要与形式参数的位置一致,只需要将参数名书写正确就可以了。这样可以避免用户需要牢记参数位置的烦恼,使函数的调用和参数传递更加灵活。
例:
def fun_bmi(person,height,weight):
'''功能:根据身高和体重计算BMI指数
person:姓名
height:身高,单位:米
weight:体重,单位:千克
'''
print(person + "的身高:" + str(height) + "米 \t 体重:" + str(weight) + "千克")
bmi=weight/(height*height) # 用于计算BMI指数,公式为"体重/身高的平方"
print(person + "的BMI指数为:"+str(bmi)) # 输出BMI指数
# 判断身材是否合理
if bmi<18.5:
print("您的体重过轻 ~@_@~\n")
if bmi>=18.5 and bmi<24.9:
print("正常范围,注意保持 (-_-)\n")
if bmi>=24.9 and bmi<29.9:
print("您的体重过重 ~@_@~\n")
if bmi>=29.9:
print("肥胖 ^@_@^\n")
#调用函数
fun_bmi(height = 1.83,weight = 60,person = '路人')
路人的身高:1.83米 体重:60千克
路人的BMI指数为:17.916330735465376
为参数设置默认值
在调用函数时,如果没有指定某个参数将出现异常,所以我们可以为参数设置默认值,即在定义函数时,直接指定形式参数的默认值。
这样,当没有传入参数时,则直接使用定义函数时设置默认值。
语法格式:def functionname(...,[parname1 = defaultvalue1])
[functionbody]
# functionname: 函数名称,在调用函数时使用。
# parname1 = defaultvalue1: 可选参数,用于指定向函数中传递的参数,并且为该参数设置默认值为defaultvalue1。
# functionbody: 可选参数,用于指定函数体,即该函数被调用后,要执行的功能代码。
注意:在定义函数时,指定默认的形式参数必须在所有参数的最后,否则将产生错误。
例:
def fun_bmi(height,weight,person = "路人"):
'''功能:根据身高和体重计算BMI指数
person:姓名
height:身高,单位:米
weight:体重,单位:千克
'''
print(person + "的身高:" + str(height) + "米 \t 体重:" + str(weight) + "千克")
bmi=weight/(height*height) # 用于计算BMI指数,公式为"体重/身高的平方"
print(person + "的BMI指数为:"+str(bmi)) # 输出BMI指数
# 判断身材是否合理
if bmi<18.5:
print("您的体重过轻 ~@_@~\n")
if bmi>=18.5 and bmi<24.9:
print("正常范围,注意保持 (-_-)\n")
if bmi>=24.9 and bmi<29.9:
print("您的体重过重 ~@_@~\n")
if bmi>=29.9:
print("肥胖 ^@_@^\n")
将person设定默认值。然后在调用函数时,可以直接输入身高,体重。
#调用函数
fun_bmi(1.83,60)
输出:
路人的身高:1.83米 体重:60千克
路人的BMI指数为:17.916330735465376
您的体重过轻 ~@_@~
可变参数
可变参数也称为不定长参数,即传入函数的实际参数可以是任意多个。
定义可变参数时,只要分为两种:一种是"*parameter",另一种是"**parameter"
*parameter
这种形式表示接收任意多个实际参数并将其放入一个元组中。
语法格式:
def functionname([formal_args,] *var_args_tuple ):
"函数_文档字符串"
function_suite
return [expression]
例:
def printcoffee(*coffeename):
print('\n我喜欢的咖啡有:')
for item in coffeename:
print(item)
printcoffee('蓝山')
printcoffee('蓝山','卡布奇洛')
printcoffee('蓝山','卡布奇洛','拿铁')
输出:
我喜欢的咖啡有:
蓝山
我喜欢的咖啡有:
蓝山
卡布奇洛
我喜欢的咖啡有:
蓝山
卡布奇洛
拿铁
如果想要使用一个已经存在的列表来作为函数的可变参数,可以在列表名称前面加"*"。
例:
def printcoffee(*coffeename):
print('\n我喜欢的咖啡有:')
for item in coffeename:
print(item)
param = ['蓝山','拿铁']
printcoffee(*param)
输出:
我喜欢的咖啡有:
蓝山
拿铁
**parameter
这种形式表示接收任意多个类似关键字参数一样显示赋值的实际参数,并将其放入一个字典中。
语法格式:
def functionname([formal_args,] **var_args_dict ):
"函数_文档字符串"
function_suite
return [expression]
例:
def printsign(**sign):
print()
for key,value in sign.items():
print("["+ key + "] 的星座是:" + value)
#调用函数
printsign(绮梦 = '水瓶座',衣衣 = '处女座')
printsign(玲 = '金牛座',君 = '天蝎座',汤 = '狮子座')
输出:
[绮梦] 的星座是:水瓶座
[衣衣] 的星座是:处女座
[玲] 的星座是:金牛座
[君] 的星座是:天蝎座
[汤] 的星座是:狮子座
声明函数时,参数中星号 * 可以单独出现
def f(a,b,*,c):
return a+b+c
如果单独出现星号 * 后的参数必须用关键字传入。
def f(a,b,*,c):
return a+b+c
f(1,2,3) # 报错
输出:
f(1,2,3) # 报错
TypeError: f() takes 2 positional arguments but 3 were given
def f(a,b,*,c):
return a+b+c
#f(1,2,3) # 报错
f(1,2,c=3) # 正常
输出:
6
返回值
在函数体内使用return语句为函数指定返回值,该返回值可以是任意类型,并且无论return语句出现在函数的什么位置,只要得到执行,就会直接结束函数的执行。
语法格式: return[value]
# value:可选参数,用于指定要返回的值,可以返回一个值,也可以返回多个值。
为函数指定返回值后,在调用函数时,可以把它赋给一个变量(如:name),用于保存函数的返回值。
如果返回一个值,那么name中保存的就是返回的一个值,该值可以是任意类型。
但如果返回的是多个值,那么name中保存的是一个元组。
说明:当函数中没有return语句时,或者省略了return语句的参数时,将返回None,即返回空值。
实例:
def fun_checkout(money):
'''功能:计算商品合计金额并进行折扣处理
money:保存商品金额的列表
返回商品的合计金额和折扣后的金额
'''
money_old = sum(money) # 计算合计金额
money_new = money_old
if 500 <= money_old < 1000: # 满500可享受9折优惠
money_new = '{:.2f}'.format(money_old * 0.9)
elif 1000 <= money_old <= 2000: # 满1000可享受8折优惠
money_new = '{:.2f}'.format(money_old * 0.8)
elif 2000 <= money_old <= 3000: # 满2000可享受7折优惠
money_new = '{:.2f}'.format(money_old*0.7)
elif money_old >=3000 : # 满3000可享受6折优惠
money_new = '{:.2f}'.format(money_old*0.6)
return money_old,money_new # 返回总金额和折扣后的金额
#*****************************调用函数***********************************#
print("\n开始结算……\n")
list_money = [] # 定义保存商品金额的列表
while True:
# 请不要输入非法的金额,否则将抛出异常
inmoney = float(input("输入商品金额(输入0表示输入完毕):"))
if int(inmoney)==0:
break # 退出循环
else:
list_money.append(inmoney) # 将金额添加到金额列表中
money = fun_checkout(list_money) # 调用函数
print("合计金额:",money[0],"应付金额:",money[1]) # 显示应付金额
开始结算……
输入商品金额(输入0表示输入完毕):2000
输入商品金额(输入0表示输入完毕):0
合计金额: 2000.0 应付金额: 1600.00
变量的作用域
局部变量
局部变量是指在函数内部定义并使用的变量,它只在函数内部有效。即函数内部的名字只在函数运行时才会创建,在函数运行之前或者运行完毕后,所有的名字都不再存在。所以,如果在函数外部使用函数内部定义的变量,就会出现NameError错误。
例:
def f_demo():
message = '唯有在被追赶时,你才会真正的奔跑'
print('局部变量message =',message) #输出局部变量的值
f_demo() #调用函数
print('局部变量message = ',message) #在函数体外输出局部变量的值
输出错误:
print('局部变量message = ',message) #在函数体外输出局部变量的值
NameError: name 'message' is not defined
全局变量
与局部变量对应,全局变量是能够作用于函数内外的变量。
如果一个变量,在函数外定义,那么不仅在函数外可以访问到,在函数内也可以访问到。在函数体外定义的变量是全局变量。
例:
message = '唯有在被追赶时,你才会真正的奔跑'
def f_demo():
print('局部变量message = ',message) #输出局部变量的值
f_demo() #调用函数
print('局部变量message = ',message) #在函数体外输出局部变量的值
输出:
局部变量message = 唯有在被追赶时,你才会真正的奔跑
局部变量message = 唯有在被追赶时,你才会真正的奔跑
说明:当局部变量与全局变量重名时,对函数体的变量进行赋值后,不影响函数体外的变量。
在函数体内定义,并且使用global关键字修饰后,该变量也就变成了全局变量。在函数体外也可以访问到该变量,并且可以在函数体内可以对其进行修改。
例:定义两个同名的全局变量和局部变量。
message = '唯有在被追赶时,你才会真正的奔跑' #全局变量
print('函数体外:message = ',message) #在函数体外输出全局变量
def f_demo():
message = '命运给予我们的不是失望之酒,而是机会之杯' #局部变量
print('函数体内:message = ',message) #在函数体内输出局部变量的值
f_demo() #调用函数
print('函数体外:message = ',message) #在函数体外输出局部变量的值
函数体外:message = 唯有在被追赶时,你才会真正的奔跑
函数体内:message = 命运给予我们的不是失望之酒,而是机会之杯
函数体外:message = 唯有在被追赶时,你才会真正的奔跑
函数内部定义的变量即使与全局变量重名,也不影响全局变量的值。那么想要在函数体内部改变全局变量的值,需要在定义局部变量时,使用global关键字修饰。
例:
message = '唯有在被追赶时,你才会真正的奔跑' #全局变量
print('函数体外:message = ',message) #在函数体外输出全局变量
def f_demo():
global message #将message声明为全局变量
message = '命运给予我们的不是失望之酒,而是机会之杯' #全部变量
print('函数体内:message = ',message) #在函数体内输出全局变量的值
f_demo() #调用函数
print('函数体外:message = ',message) #在函数体外输出全局变量的值
输出:
函数体外:message = 唯有在被追赶时,你才会真正的奔跑
函数体内:message = 命运给予我们的不是失望之酒,而是机会之杯
函数体外:message = 命运给予我们的不是失望之酒,而是机会之杯
从上面可以看出,在函数体内部修改了全局变量。
另外,虽然Python允许全局变量,和局部变量重名,但是实际开发中还是不建议这么做,因为容易造成混淆,分不清哪个是全局变量,哪个是局部变量。
匿名函数
匿名函数是指没有名字的函数,应用在需要一个函数,但又不想费神去命名这个函数的场合。但通常情况下,这样的函数只使用一次。
使用lambda表达式创建匿名函数。
语法格式: result = lambda[arg1 [,arg2, ... ,argn]]:expression
# result : 用于调用lambda表达式。
# [arg1 [,arg2, ... , argn]] :可选参数,用于指定要传递的参数列表,多个参数间用","分隔
# expression :必选参数,用于指定一个实现具体功能的表达式。如果有参数,那么在该表达式中将应用这些参数。
注意:使用lambda表达式时,参数可以有多个,用","隔开,但是表达式只能有一个,即只能返回一个值,而且也不能出现在其他非表达式语句上(如:for 或者 while)。
例:计算一个圆的面积的函数。
import math
def cir(r):
result = math.pi*r*r
return result
r = 10
print('半径为',r,'的圆的面积为',cir(r))
输出:
半径为 10 的圆的面积为 314.1592653589793
使用lambda表达式:
import math
r = 10
result = lambda r:math.pi*r*r
print('半径为',r,'的圆的面积为',result(r))
输出:
半径为 10 的圆的面积为 314.1592653589793
虽然使用lambda表达式比使用自定义函数的代码减少一些,但是在使用lambda表达式时,需要定义一个变量,用于调用lambda表达式,否则将会出现报错。
lambda表达式的首要用途是指定短小的回调函数。
实例:
定义一个列表,在使用srot()排序,并在调用sort()方法时,通过lambda表达式指定排序规则
bookinfo = [('不一样的卡梅拉(全套)',22.50,120),('摆渡人',23.40,36.00),('福尔摩斯探案全集8册',22.50,128)]
# 元组的第一个元素为商品名称,第二个元素为折扣价,第三个元素为原价。
print('爬取到的商品信息:\n',bookinfo,'\n')
bookinfo.sort(key=lambda x:(x[1],x[1]/x[2])) # 按指定规则进行排序
print('排序后的商品信息:\n',bookinfo)
输出:
爬取到的商品信息:
[('不一样的卡梅拉(全套)', 22.5, 120), ('摆渡人', 23.4, 36.0), ('福尔摩斯探案全集8册', 22.5, 128)]
排序后的商品信息:
[('福尔摩斯探案全集8册', 22.5, 128), ('不一样的卡梅拉(全套)', 22.5, 120), ('摆渡人', 23.4, 36.0)]