自带函数
比如说当我们需要实现“打印”这个功能,我们会用到print();当我们需要实现“获取数据长度”这个功能,我们会要到len()。这些都是设定好了,可以直接拿过来就用的功能,这就叫做“组织好的代码”。
函数(Function)能实现的功能从简单到复杂,各式各样,但其本质是相通的:“喂”给函数一些数据,它就能内部消化,给你“吐”出你想要的东西。
函数后面都跟了个括号。而括号里放的东西,也就是我们需要输入的数据,它在函数中被称作【参数】。【参数】指向的是函数要接收、处理怎样的数据。
比如print()函数的括号里可以放不同的参数,根据你放的参数不同,print()函数会帮你在屏幕上显示不同的内容。
print('Hello World')
print('万物的终极答案')
print(42)
括号里面的字符串和整数,都是print() 函数的参数。
定义函数
def 函数名(参数1,参数2...参数n):
函数体
return 语句
举个栗子:
def greet(name):
print(name+'早上好')
return
(打招呼的英文是greet,你写say_hello或别的也行,其实理论上你随便起什么都可以,但别人也看得懂是最好的啦。)
来一起读代码。第1行:def的意思是定义(define),greet是【函数名】(自己取的),再搭配一个括号和冒号,括号里面的name是参数(参数名也是自己取)。
第2行:def下一行开始缩进的代码是函数要实现的功能,也叫【函数体】。这里的函数体展现出的功能就是:打印出“name+ 早上好”这句话。
第3行:一个简单的return。函数内部一旦遇到return语句,就会停止执行并返回结果。没有return语句的函数,Python也会在末尾隐性地加上return None,即返回None值(return None可以简写为return。)所以你也会看到,我们接下来的很多例子是省略了return语句的。
定义函数的语法并不难,但有些注意事项一开始要特别注意,我标记在下面代码块的注释里,请你一定仔细阅读下。
#函数名:最好是取体现函数功能的名字,一般用小写字母和单下划线、数字等组合
def greet(name):
#参数:根据函数功能,括号里可以有多个参数,也可以不带参数,命名规则与函数名相同
#规范:括号是英文括号,后面的冒号不能丢
print(name+'早上好')
#函数体:函数体就是体现函数功能的语句,要缩进,一般是四个空格
return
看到第三行注释,你可能会有点疑问,怎么括号里可以有参数,又能没有参数?接下来我举个小例子,你可以对比一下。
#第一个函数
def pika1():
print('我最喜爱的神奇宝贝是皮卡丘')
#第二个函数
def pika2(name):
print('我最喜爱的神奇宝贝是'+name)
#第三个函数
def pika3(name,person):
print('我最喜爱的神奇宝贝是'+name)
print('我最喜爱的驯兽师是'+person)
这几个函数的功能都是打印出句式相同的话,区别在于第一个函数总是输出固定的一句话,所以不需要带参数。
而第二个函数需要参数name的参与,所以括号里需要带上name,第三个函数则需要两个参数来完成功能。所以说,参数的数量需要视函数想要实现什么功能来设置。
定义完函数的下一步就是调用函数,召唤神奇宝贝的时刻到了。
调用函数
在Python里,就是输入函数名和参数对应的值。就像这样:
def pika2(name):
print('我最喜爱的神奇宝贝是'+name)
pika2('皮卡丘') #调用函数,输入函数名pika()并输入参数'皮卡丘'
pika2('喷火龙') #调用函数,输入函数名pika()并输入参数'喷火龙'
请阅读代码并运行一下:
def pika1():
print('我最喜爱的神奇宝贝是皮卡丘')
#该函数没有参数,直接调用函数名。记得英文括号一定不能少
pika1()
def pika2(name):
print('我最喜爱的神奇宝贝是'+name)
#需要给参数name赋值,每次调用都可以给参数赋不同的值
pika2('皮卡丘')
pika2('喷火龙')
def pika3(name,person):
print('我最喜爱的神奇宝贝是'+name)
print('我最喜爱的驯兽师是'+person)
#需要给两个参数分别赋值,并用逗号隔开,否则会报错
pika3('卡比兽','小智')
通过这个例子,我们明白调用函数最关键的是:得弄清楚这个函数有多少个参数,如何给参数赋值,这个过程在函数里叫做参数的传递(pass)。
函数重要概念
主要的参数类型有:位置参数、默认参数、不定长参数。我会用一个案例把这些参数串起来。
假设你最近开了一家深夜食堂,顾客可以任意点菜。但因为人手不足,所以只能为每个人提供一份开胃菜和一份主食。如果写成函数的形式,这个函数就会有两个参数。
def menu(appetizer,course):
print('一份开胃菜:'+appetizer)
print('一份主食:'+course)
menu('话梅花生','牛肉拉面')
这里的’话梅花生’和’牛肉拉面’是对应参数appetizer和course的位置顺序传递的,所以被叫作【位置参数】 ,这也是最常见的参数类型。之前的神奇宝贝函数也有用到:
def pika3(name,person):
print('我最喜爱的神奇宝贝是'+name)
print('我最喜爱的驯兽师是'+person)
pika3('卡比兽','小智')
接下来请你观察下面代码不同的调用形式
def menu(appetizer,course):
print('一份开胃菜:'+appetizer)
print('一份主食:'+course+'\n')
#还记得转义字符\n吧,表示换行
menu('牛肉拉面','话梅花生')
menu('话梅花生','牛肉拉面')
#如果采用下面这种形式传递,就不需要理会参数位置
menu(course='牛肉拉面',appetizer='话梅花生')
好,位置参数是怎么一回事,你现在已经差不多明白了吧。
回到这个食堂的故事。经营了一阵子之后,为了吸引更多的人流,你决定给每个顾客免费送上一份甜品绿豆沙,这时候你就可以用到【默认参数】,注意:默认参数必须放在位置参数之后。
def menu(appetizer,course,dessert='绿豆沙'):
print('一份开胃菜:'+appetizer)
print('一份主食:'+course)
print('一份甜品:'+dessert)
menu('话梅花生','牛肉拉面')
#因为已经默认将'绿豆沙'传递给dessert,调用时无须再传递。
如果一个参数的值是相对固定的,那么设置默认参数就免去了每次都要传递的麻烦。但默认参数并不意味着不能改变,试试运行下列结果。
def menu(appetizer,course,dessert='绿豆沙'):
print('一份开胃菜:'+appetizer)
print('一份主食:'+course)
print('一份甜品:'+dessert)
menu('话梅花生','牛肉拉面')
menu('话梅花生','牛肉拉面','银耳羹')
#银耳羹对应参数dessert
一个萝卜一个坑,因为前两个参数已经有对应的值传递,Python会自动将’银耳羹’传递给参数dessert。
了解完默认参数,我们接着往下看。
后来呢,盛夏来袭,你觉得卖烧烤是个不错的主意。但问题是每个人点的烤串数量都不同,你也不能限定死数量,这时候【不定长参数】就能派上用场,即不确定传递参数的数量。
它的格式比较特殊,是一个星号*加上参数名,来看下面的例子。
def menu(*barbeque):
print(barbeque)
menu('烤鸡翅','烤茄子','烤玉米')
#这几个值都会传递给参数barbeque
你会发现输出的是这样的结果:(‘烤鸡翅’, ‘烤茄子’, ‘烤玉米’),这种数据类型叫做元组(tuple),我们来复习一下:
元组的写法是把数据放在小括号()中,它的用法和列表用法类似,主要区别在于列表中的元素可以随时修改,但元组中的元素不可更改。
icon
当然我们也可以先生成一个元组,再传入参数。上述代码等价于:
order=('烤鸡翅','烤茄子','烤玉米')
#元组的长度没有限制
def menu(*barbeque):
print(barbeque)
menu(*order)
和列表一样,元组是可迭代对象,这意味着我们可以用for循环来遍历它,这时候的代码就可以写成:
def menu(appetizer,course,*barbeque,dessert='绿豆沙'):
print('一份开胃菜:'+appetizer)
print('一份主菜:'+course)
print('一份甜品:'+dessert)
for i in barbeque:
print('一份烤串:'+i)
menu('话梅花生','牛肉拉面','烤鸡翅','烤茄子','烤玉米')
需要注意的是,这时候默认参数也需要放在不定长参数的后面,即dessert=’绿豆沙’要放在*barbeque后面,否则传递的值会对应不上。
return语句
前面我们提到,return是返回值,当你输入参数给函数,函数就会返回一个值给你。事实上每个函数都会有返回值,像我们之前学过的len()函数。
a=[1,2,3]
print(len(a))
当你把参数a放进len() 函数中,它返回来的是3这个数值(列表的长度)。之后,我们就可以调用这个值,比如用print()函数打印出来或干点儿别的。
像常见的type()函数、数据类型转换函数,还有我们之前学过的bool()都是这样,会返回一个值。
而print()函数本身比较特殊,它在屏幕上显示完相关的文本内容就没了,并不会返回一个值给我们。所以,它返回的是空值(None)。
在自定义函数的时候,我们就可以用return语句规定该函数要返回什么值给我们。带return语句的函数是这样的:
def niduoda(age):
if age < 12:
return '哈,是祖国的花朵啊'
elif age < 25:
return '哇,是小鲜肉呢'
else:
return '嗯,人生才刚刚开始'
print(niduoda(30))
参数值30在条件判断中满足else的条件,所以函数返回’嗯,人生才刚刚开始’,再由print()函数打印出来。
提醒一下,函数也是可以互相嵌套的,在这个例子中,niduoda()函数就被嵌套在print()函数里。
可能你会觉得在这个例子中,直接用print不就行了吗,为啥还要用return呢?还有,我们前面讲了那么多函数,好像都是省略了return的啊,比如刚讲的深夜食堂函数和神奇宝贝函数:
#神奇宝贝函数
def pika2(name):
print('我最喜爱的神奇宝贝是'+name)
pika2('皮卡丘')
pika2('喷火龙')
#深夜食堂函数
def menu(appetizer,course,*barbeque,dessert='绿豆沙'):
print('一份开胃菜:'+appetizer)
print('一份主菜:'+course)
print('一份甜品:'+dessert)
for i in barbeque:
print('一份烤串:'+i)
menu('话梅花生','牛肉拉面','烤鸡翅','烤茄子','烤玉米')
其实是因为在这些例题中,我们的函数功能都是第一时间把参数打印出来。而在很多时候,当多个函数之间相互配合时,我们并不需要第一时间就将结果打印出来,而是需要将某个返回值先放着,等到需要的时候再做进一步的处理。
下面来看个例子:
icon
在我们关于爱情的天真幻想中,我希望我的梦中情人拥有XXX的脸蛋和XXX的身材。
icon
现在需求如下:一、分别定义两个函数,参数为人名,能够返回字符串’XXX的脸蛋’和’XXX的身材’;二、将上述两个函数的返回值拼接在一起之后,再打印出来。请你先思考一下,再点击回车。
相信对你来说并不难,如果一步步地写,代码应该是这样的:
def face(name):
return name + '的脸蛋'
#该函数返回字符串'XXX的脸蛋'
def body(name):
return name + '的身材'
#该函数返回字符串'XXX的身材'
face('李若彤')
body('林志玲')
#分别调用face()和body()函数
print('我的梦中情人:'+face('李若彤') +' + ' + body('林志玲'))
#将返回值拼接并打印出来
前面也讲到,函数可以互相嵌套,所以第7、8行调用face()和body()函数的两行代码可以省略,因为第12行的print()函数中其实已经有调用这两个函数了。
def face(name):
return name + '的脸蛋'
def body(name):
return name + '的身材'
print('我的梦中情人:'+face('李若彤') +' + ' + body('林志玲'))
这只是一个非常简单的例子,在类似这种多个函数相互配合的代码中,我们就会非常需要return语句,来帮我们先保留某个函数的返回值,等要用到的时候再调出来用。
但是这样的代码还有个问题,当我想多次调用函数的时候,就需要先复制print那行代码,再分别修改两个函数里的参数。这样的操作既不简洁,也不优雅。就像这样:
def face(name):
return name + '的脸蛋'
def body(name):
return name + '的身材'
print('我的梦中情人:'+face('李若彤') +' + ' + body('林志玲'))
#要再次调用就要复制一遍,然后改参数
print('我的梦中情人:'+face('新垣结衣') +' + ' + body('长泽雅美'))
所以更常见的做法是:再定义一个主函数main(),参数调用前两个函数的返回值。先给出代码,你可以琢磨一下,主要思考第5行和第6行代码。
def face(name):
return name + '的脸蛋'
def body(name):
return name + '的身材'
def main(dream_face,dream_body):
return '我的梦中情人:' + face(dream_face) + ' + ' + body(dream_body)
print(main('李若彤','林志玲'))
print(main('新垣结衣','长泽雅美'))
main()函数内部分别调用了face()和body()函数,参数dream_face和dream_body传递给了face()和body()函数的参数name,得到返回值,并打印。看起来有点绕,我们将函数运行的步骤分解,就一目了然了。
!
我们可以总结一下:
需要多次调用函数时,可以再定义一个主函数main(),调用非主函数的返回值。
还是看这段代码:
def face(name):
return name + '的脸蛋'
def body(name):
return name + '的身材'
print('我的梦中情人:'+face('李若彤') +' + ' + body('林志玲'))
在这段代码中,我们定义了两个函数,每个return语句分别返回关于“脸蛋”和“身材”的值。如果要一次性返回这两个值,我会这样做,你先看代码:
def lover(name1,name2):
face = name1 + '的脸蛋'
body = name2 + '的身材'
return face,body
a=lover('李若彤','林志玲')
print('我的梦中情人:'+a[0]+' + '+a[1])
为什么要这样写,第7行代码是啥意思?怎么看上去像是列表?你大概有这样的疑惑了吧。
icon
我们先来看看,一次性返回的两个值,是什么数据类型。
#请直接运行代码
def lover(name1,name2):
face = name1 + '的脸蛋'
body = name2 + '的身材'
return face,body
a=lover('李若彤','林志玲')
print(a)
是(‘李若彤的脸蛋’, ‘林志玲的身材’)这样一个元组,对不对?又是元组。
事实上,Python语言中的函数返回值可以是多个,而其他语言都不行,这是Python相比其他语言的简便和灵活之处。一次接受多个返回值的数据类型就是元组。
def lover(name1,name2):
face = name1 + '的脸蛋'
body = name2 + '的身材'
return face,body
a=lover('李若彤','林志玲')
#此时return的值为元组 a = ('李若彤的脸蛋', '林志玲的身材')
print('我的梦中情人:'+a[0]+' + '+a[1])
现在你大概对return的作用有了更深的了解吧。我们继续总结:
python的函数返回值可以是多个,多个返回值的数据类型是元组(tuple)
最后需要再强调的是,没有return语句的函数会默认返回None值。运行下列代码,并观察结果。
#第一个函数
def fun():
a ='I am coding'
print(fun())
#第二个函数
def fun():
a='I am coding'
return a
print(fun())
第一个函数因为没有return语句,返回None值,所以打印出None。
没有return语句的函数会默认返回None值
此外,return还有一个“副作用”:一旦函数内部遇到return语句,就会停止执行并返回结果。你可以运行下列的代码:
def fun():
return 'I am coding.'
return 'I am not coding.'
print(fun())
函数内部遇到第一个return就会返回,所以只会打印出’I am coding’。
好啦,关于return语句,我们的知识讲解就到这里。
!
现在呢,趁热打铁,巩固一下学过的知识。
题目是这样的:一、定义一个带有两个参数的函数,函数的功能是返回两个参数中较大的那个值;二、调用函数,将99的平方和8888赋值给参数,并将较大值打印出来。
def big_num(x,y):
if x>y:
return x
elif x==y:
return '一样大'
else:
return y
print(big_num(99**2,8888))