• Python 函数


    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

    定义一个函数

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

    def max(a,b):
        if a > b:
            return a
        else:
            return b
    

    请注意,return表示返回的意思,函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。

    函数返回值

    有时候函数是没有返回结果的,这个时候从函数获取到的是一个空值None。

    def square_of_sum(list):
        sum = 0
        for i in list:
            sum += i**2
        
        print(sum)
    
    result = square_of_sum([1,2,3])
    print(result) #None
    
    
    

    除了返回None、一个值以外,函数也可以返回多个值,在函数中,如果需要返回多个值,多个值之间使用逗号分隔即可,但是需要注意顺序。
    示例:定义一个函数sub_sum(),这个函数接收一个列表作为参数,函数返回列表所有奇数项的和以及所有偶数项的和:

    def sub_sum(L):
        odd_sum = 0  # 奇数和
        even_sum = 0 # 偶数和
        for i in L:
            if i % 2==0:
                even_sum +=i
            else:
                odd_sum+=i
        
        return odd_sum,even_sum
    
    print(sub_sum(range(0,100))) # (2500, 2450)
    
    

    递归函数

    如果在一个函数内部调用其自身,这个函数就是递归函数。
    举个例子,我们来计算阶乘 n! = 1 * 2 * 3 * ... * n,用函数 fact(n)表示,可以看出:
    fact(n) = n! = 1 * 2 * 3 * ... * (n-1) * n = (n-1)! * n = fact(n-1) * n
    所以,fact(n)可以表示为 n * fact(n-1),只有n=1时需要特殊处理。
    于是,fact(n)用递归的方式写出来就是:

    def fact(n):
        if n==1:
            return 1
        return n * fact(n - 1)
    

    这个fact(n)就是递归函数。
    使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。
    请分别使用循环和递归的形式定义函数,求出1~100的和:

    # coding=utf-8
    def sum_b(n):
        if n==1:
            return n
        return sum_b(n-1)+n
    
    def sum_a(n):
        sum = 0
        for i in range(1,n+1):
            sum +=i
    
        return sum
    
    print(sum_a(100))
    print(sum_b(100))
    

    函数参数

    函数参数可以是任意的数据类型,只要函数内部逻辑可以处理即可。

    为了保证函数的正常运行,有时候需要对函数入参进行类型的校验,Python提供isinstance()函数,可以判断参数类型,它接收两个参数,第一个是需要判断的参数,第二个是类型。

    isinstance(100, int) # ==> True
    isinstance(100.0, int) # ==> False
    isinstance('3.1415926', str) # ==> True
    

    任务
    请实现函数func,当参数类型为list时,返回list中所有数字类型元素的和,当参数类型为tuple时,返回tuple中所有数字类型元素的乘积。

    def func(param):
        if(isinstance(param,list)):
            sum = 0
            for i in param:
                sum +=i
    
            return sum
    
        elif(isinstance(param,tuple)):
            result = 1
            for i in param:
                result = result * i
    
            return result
        else:
            return 0
        
    print(func([1,2,3,4])) # 10
    print(func((1,2,3,4))) # 24
    

    注意:

    在 def 语句中,位于函数名后面的变量通常称为形参,而调用函数时提供的值称为实参

    默认参数

    定义函数的时候,还可以有默认参数,默认参数的意思是当这个参数没有传递的时候,参数就使用定义时的默认值。
    函数的默认参数的作用是简化调用,你只需要把必须的参数传进去。但是在需要的时候,又可以传入额外的参数来覆盖默认参数值。

    我们来定义一个计算 x 的N次方的函数:

    def power(x, n):
        s = 1
        while n > 0:
            n = n - 1
            s = s * x
        return s
    

    假设计算平方的次数最多,我们就可以把 n 的默认值设定为 2:

    def power(x, n=2):
        s = 1
        while n > 0:
            n = n - 1
            s = s * x
        return s
    

    这样一来,计算平方就不需要传入两个参数了:

    power(5) # ==> 25
    

    另外需要注意的是,由于函数的参数按从左到右的顺序匹配,所以默认参数只能定义在必需参数的后面,否则将会出现错误。

    练习:请定义一个 greet() 函数,它包含一个默认参数,如果没有传入参数,打印 Hello, world.,如果传入参数,打印Hello, 传入的参数内容:

    def greet(s='world.'):
        print('Hello, '+s)
    
    greet()
    greet('libai')
    

    可变参数

    除了默认参数,Python函数还接收一种参数叫做可变参数,可变参数即任意个参数的意思,可变参数通常使用*args来表示。

    def func(*args):
        print('args length = {}, args = {}'.format(len(args), args))
    
    func('a') # ==> args length = 1, args = ('a',)
    func('a', 'b') # ==> args length = 2, args = ('a', 'b')
    func('a', 'b', 'c') # ==> args length = 3, args = ('a', 'b', 'c')
    

    注意,在使用上,Python会把可变参数定义为一个tuple,所以在函数内部,把可变参数当作tuple来使用就可以了,比如可以通过位置下标取出对应的元素等。
    定义可变参数的目的也是为了简化调用。假设我们要计算任意个数的平均值,就可以定义一个可变参数:

    def average(*args):
        sum = 0
        for item in args:
            sum += item
            
        avg = sum / len(args)
        return avg
    

    这样,在调用的时候,我们就可以这样写:

    average(1, 2) # ==> 1.5
    average(1, 2, 2, 3, 4) # ==> 2.4
    average()
    # 报错
    # Traceback (most recent call last):
    # ZeroDivisionError: division by zero
    

    在执行average()的时候,却报错了,这是因为在使用可变参数时,没有考虑周全导致的,因为可变参数的长度可能是0,当长度为0的时候,就会出现除0错误。因此需要添加保护的逻辑,这是同学在使用过程中需要特别注意的。

    def average(*args):
        sum = 0
        if len(args)==0:
            return 0
        for item in args:
            sum += item
            
        avg = sum / len(args)
        return avg
    

    可变关键字参数

    可变参数在使用上确实方便,函数会把可变参数当作tuple去处理,tuple在使用上有一定的局限性,比如有时候想找到特定位置的参数,只能通过下标的方式去寻找,如果顺序发生变化得时候,下标就会失效,函数逻辑就得重新修改实现。
    Python函数提供可变关键字参数,对于可变关键字参数,可以通过关键字的名字key找到对应的参数值,想想这和我们之前学习过的什么类似?是的没错,dict,Python会把可变关键字参数当作dict去处理;对于可变关键字参数,一般使用**kwargs来表示。
    例如,想要打印一个同学的信息,可以这样处理:

    def info(**kwargs):
        print('name: {}, gender: {}, age: {}'.format(kwargs.get('name'), kwargs.get('gender'), kwargs.get('age')))
    
    info(name = 'Alice', gender = 'girl', age = 16)
    

    对于一个拥有必需参数,默认参数,可变参数,可变关键字参数的函数,定义顺序是这样的:

    def func(param1, param2, param3 = None, *args, **kwargs):
        print(param1)
        print(param2)
        print(param3)
        print(args)
        print(kwargs)
    
    func(100, 200, 300, 400, 500, name = 'Alice', score = 100)
    # ==> 100
    # ==> 200
    # ==> 300
    # ==> (400, 500)
    # ==> {'name': 'Alice', 'score': 100}
    

    当然,这么多类型的参数,很容易导致出错,在实际使用上,不建议定义这么多的参数。

    练习:编写一个函数,它接受关键字参数name,gender,age三个字符串,分别代表同学的名字、性别和年龄,请把同学的名字、性别和年龄打印出来:

    def print_student(**stu):
        print('name:{},gender:{},age:{}'.format(stu.get('name'),stu.get('gender'),stu.get('age')))
    
    print_student(name='libai',age='20',gender='1')
    # name:libai,gender:1,age:20
    
  • 相关阅读:
    DQL:data query language用来查询数据库表中的数据
    Mysql训练:两个表中使用 Select 语句会导致产生 笛卡尔乘积 ,两个表的前后顺序决定查询之后的表顺序
    最常用SQL joins:内连接(交集)、左外连接、右外连接、左连接、右连接、全连接(并集),全外连接
    空间异常即刻诊断,华为云数据管理服务DAS又出新招~
    【华为云技术分享】【论文阅读】增量式物体检测
    【华为云技术分享】如何让敏捷回顾会议更有效果,这样做就对了
    【华为云技术分享】如何处理暗数据?
    【华为云技术分享】MongoDB经典故障系列五:sharding集群执行sh.stopBalancer()命令被卡住怎么办?
    【华为云技术分享】云图说 | 初识云耀云服务器,打造“极优、极简”的云上体验
    【华为云技术分享】十分钟从入门到精通(上)—对象存储服务的OBS权限配置
  • 原文地址:https://www.cnblogs.com/hanliukui/p/16438731.html
Copyright © 2020-2023  润新知