• 自带函数

    比如说当我们需要实现“打印”这个功能,我们会用到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,得到返回值,并打印。看起来有点绕,我们将函数运行的步骤分解,就一目了然了。

    函数.png

    我们可以总结一下:
    需要多次调用函数时,可以再定义一个主函数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语句,我们的知识讲解就到这里。

    return.png

    现在呢,趁热打铁,巩固一下学过的知识。

    题目是这样的:一、定义一个带有两个参数的函数,函数的功能是返回两个参数中较大的那个值;二、调用函数,将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))
    

建议的主题

  • 1
  • 1
  • 1
  • 1