Python学习笔记之函数

一、函数的定义

        在Python中,定义了一个函数使用def语句,一次写出函数名、括号、中括号的参数和冒号:,然后在缩进快中编写函数体,函数的返回值用return语句进行返回。

        我们以自定义一个求绝对值的my_abs(),并对其进行函数调用,例:

    def my_abs(x):     
        if x >= 0:     
            return x   
        else :         
            return -x  
                   
    num = 15           
    print(my_abs(num)) 

       请注意,函数体内部的语句在执行时一旦遇到了return时,函数逻辑机就执行完毕并将结果返回。因此函数内部通过条件判断和循环可以实现非常复杂的逻辑。

       如果没有return语句,函数执行完毕后也会返回结果,只是结果为None。return None可以简写为return。

       return 语句的后面如果有变量或者值,则函数存在返回值,那么可以将函数赋值给一个变量。

      在函数名的括号内写的变量被称为函数参数,函数参数可有可无。在python我们的参数有实参和形式参数(实参)之分,对函数定义时的函数名括号内的参数被称作形式参数,函数调用时函数名括号内的参数被称作实参,该参数必须是实际存在的。

    

二、函数的多个返回值

      在我们Python中,函数的返回值只有一个,如果我们非要返回多个值,python解释器会将所有的返回值封装为一个元祖(tuple)数据类型进行返回。在语法上返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数的多返回值就是一个tuple,只是写起来更加方便。

    def fun(list_tmp):
        max_num = max(list_tmp)
        min_num = min(list_tmp)
        avg_num = sum(list_tmp)/len(list_tmp)
        return max_num , min_num , avg_num

    list_num = [10,3,7,2,8]

    tmp = fun(list_num)

    print(tmp,type(tmp))

输出 : 

(10, 2, 6.0) <class 'tuple'>        
       由此可见,返回值只能是一个值,当有多个返回值时,python解释器会将所有的返回值封装为一个tuple进行返回,依旧做到了,函数返回值只有一个。

二、函数的形参类型

        python中函数的形参右下面几种,必选参数,默认参数,可变参数,关键字参数。

  (1)必选参数

       如果一个函数(或方法、过程、自定义函数等)带有一个或多个参数,那么你在调用这个函数时也必须带有相同数量的参数,否则就会提示“必选参数”的错误。

    def add(x, y, z): 
        return x + y + z
    print(add(2,3,4))

 输出:       

    9

       上面代码中,x,y,z 就是形参中的必选参数,我们的add(x,y,z)不论在什么地方调用时,总是需要三个实参。=,少一个都不可以。

 (2)默认参数

        如果一个函数在定义的时候,并对其参数进行了赋值,那么就说这个参数是该函数的一个默认参数,函数调用时,默认参数可以不用使用实参进行传值,会使用在函数定义时赋给的值。

    #函数功能:x的y次方
    def mypow(x, y=2):
         return x ** y
    print(mypow(9))       #函数调用时没有给形参y赋值,因此y默认等于2
    print(mypow(4,3))     #函数调用时对形参x,y都进行了赋值,y不在使用默认值,使用实参传给的值   

        在定义函数时,我们需要将默认参数放在必选参数的后面,否则python就会报错。当函数有多个参数是,把变化大的参数放在前面,变化小的参数放在后面,变化下的参数就可以作为默认参数。

        使用默认参数最好的就是帮助我们降低了函数调用的难度。我们在使用默认参数时应该注意list类型的默认参数。

        当我们使用可变数据类型作为函数参数时,我们会出现如下错误

例1:

    def fun(tmp = []):
        tmp.append('Hello')
        return tmp
    list_num = []
    print(fun(list_num))
    print(fun(list_num))

 输出:

    ['Hello']
    ['Hello', 'Hello']

 例2:

    def fun(tmp = {4,3,2,6}):
        tmp.pop()
        return tmp
    print(fun())
    print(fun())

输出:

   {3, 4, 6}
   {4, 6}

         这是因为Python函数在定义时,默认参数tmp的值就被计算出来,即[ ],它是一个可变的数据类型,因为默认参数tmp也是一个变量,它指向对象[ ] ,如果改变了L的内容,则下次调用时,默认参数的内容就会发生改变,不再是函数定义时的 [ ]了

       所以我们在定义默认参数时要牢记:默认参数必须执行不变对象。像上面的例子,我们可以None这个对象来实现。

        使用不变对象作为函数参数,不变对象一旦创建,对象内部的数据就不能被修改,这样就减少了由于修改数据导致的错误,由于对象不变,多任务的环境下同时读取对象就不需要加锁,同时一点问题也没有。

 (3)可变参数

        在python中,还可以定义可变参数,可变参数就是传入的参数的个数是可变的,可以是0~n任意个参数,定义一个函数时,我们必须确定输入的参数,如果参数不确定,将多个实参作为一个list或tuple传入函数。但是这样在我们调用该函数时需要对该函数的实参进行组装,变为一个list或tuple。

        如果我们使用可变参数对函数定义,那么我们在函数调用时就不用将多个实参变为list或tuple,可以直接输入多个实参。

    def add1(*number):             #该函数使用可变参数
        sum = 0
        for num_tmp in number:
            sum += num_tmp
        return sum

    def add2(number):             #该函数没有使用可变参数
        sum = 0
        for num_tmp in number:
            sum += num_tmp
        return sum

    print(add1(1,2,3,5))         #add1() 函数可以传入多个实参
    print(add2([1,2,3,5]))       #add2() 函数只能传一个参数,如果传多个实参,需要对实参进行组装

输出:    

    11
    11

        定义可变参数和定义list或tuple相比,仅仅在参数前面加了一个 *  号。但在函数内部,number接收的是一个tuple,因此函数代码完全不变。

        我们可以在add2(*number)函数中添加print(type(number)),来看看结果:

    def add1(*number):
        print(type(number))
        sum = 0
        for num_tmp in number:
            sum += num_tmp
        return sum
    print(add1(1,2,3,5))
输出:
    <class 'tuple'>
    11

        我们发现number在加了 * 号后变成了一个元组数据类型。

        如果我们已经有了一个元组或list,要调用一个带有可变参数的函数怎么办?

        python 允许你在实参list或tuple前面添加一个 * 号,这样就把list或tuple的元素变成可变参数传进去。

    def add1(*number):
        print(type(number))
        sum = 0
        for num_tmp in number:
            sum += num_tmp
        return sum

    list_tmp = [1,2,3,5]
    print(add1(1,2,3,5))
    print(add1(*list_tmp))

输出:

    <class 'tuple'>
    11
    <class 'tuple'>
    11
        

 (4)关键字参数

        可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。

    def fun(**kwargs):
        print(kwargs,type(kwargs))
    fun(a=1,b=2,c=3)

输出:

    {'a': 1, 'b': 2, 'c': 3} <class 'dict'>

         如果我们已经有了一个dict类型的变量,那么我们调用含有关键字参数的的函数时需要,将dict类型的数据当做实参传给形参时,我们需要dict前面加 *  然后再讲该dict转为关键字参数传进去。

    dict_tmp ={'a':1,'b':2,'c':2}
    def fun(**kwargs):
        print(kwargs,type(kwargs))
    fun(**dict_tmp)

(2)参数组合

        在python 中定义函数,可以使用必选参数、默认参数、可变参数和关键字参数,这四种参数都可以一起使用,或者只使用其中某些,但是注意,参数定义的顺序必须是:必选参数,默认参数,可变参数,和关键字参数。 

        对于任意函数都可以通过func(*args,**kwargs)的形式去调用它,无论它的形参时如何定义的。

三、函数的练习

    第一题:

        对于一个十进制的整数,定义f(n)为其个位数字的平方和,如:

        f(13)  = 1**2 + 3**2 =10
        f(207) =  2**2 + 0**2 + 7**2 = 53
        下面给出三个正整数k,a,b,你需要计算有多少个正整数n满足a<=n<=b,且k*f(n) = n
输入:

        第一行包含3个整数k,a,b,k>=1 ,a,b<=10**18 ,a<=b;

输出:输出对应的答案。

示例 :

       输入: 51 5000 10000
       输出: 3

    #其个位数字的平方和
    def f(n):
        res = 0
        for item in str(n):
            res += int(item) ** 2
        return res

    #判断是否满足k*f(n) == n
    #满足 返回True 否则返回False
    def isOk(k, n):
        if k * f(n) == n:
            return True
        else:
            return False


    def main():
        str1 = input('输入:')
        list1 = str1.split()
        print(list1)
        k = int(list1[0])
        a = int(list1[1])
        b = int(list1[2])
        count = 0
        for i in range(a, b + 1):
            if isOk(k, i):
                count += 1

        print(count)

    main()

 第二题:

       编写一个名为collatz()的函数,它有一个名为number的参数。如果参数是偶数,那么collatz()就打印出number//2,并返回该值。如果number是奇数,collatz()就打印并返回3*number+1。然后编写一个程序,让用户输入一个整数,并不断对这个数调用collatz(),直到函数返回值1(令人惊奇的是,这个序列对于任何整数都有效,利用这个序列,你迟早会得到1!既使数学家也不能确定为什么。你的程序在研究所谓的“Collatz序列”,它有时候被称为“最简单的、不可能的数学问题”)。
输入:
    3
输出:
    10
    5
    16
    8
    4
    2
    1

    def collatz(number):
        if number%2 ==0:
            print(number//2)
            return number//2
        else:
            print(3*number+1)
            return (number * 3) + 1


    def main():
        number = int(input("Num:"))
        number = collatz(number)
        while number!=1:
            number=collatz(number)
            pass

    main()

四、函数的参数检测

         我们在使用一些函数时,如果传入的参数不符合函数的要求,我们的程序有可能会报错,我们可以在向函数传递实参的时候,看一下函数的说明,看看函数需要什么样的参数。我们在定义一个函数的时候,如果这个函数比较复杂,我们会写函数说明,以便在调用的时候帮助我们。
def add(x:int, y:int)->int:       #变量名:数据类型   这样子也是函数说明中的一部分。
    """              
    add: sum x and y
    :param x: int,float,.....
    :param y: int,float.....
    :return: int
    """
    if isinstance(x,(int,float,complex)) and isinstance(y,(int,float,complex)):
        return x + y
    else:
        print("Error")

        定义一个如上的函数,"""  """之间的内容就是我们的函数说明,我们还用的了isinstance(x,type)函数,进行变量类型检测。

        使用help(add) 我们的看到函数说明如下:

    Help on function add in module __main__:

    add(x:int, y:int) -> int
        add: sum x and y
    
        :param x: int,float,.....
        :param y: int,float.....
        :return: int
        这样,我们就可以通过函数说明,正确的调用函数了

    

猜你喜欢

转载自blog.csdn.net/m0_37717595/article/details/80246188