函数

作者: kris_lp | 来源:发表于2018-03-09 19:38 被阅读0次

    定义函数

    定义函数用def语句,格式:def 函数名(自变量) :函数名称的定义规则和变量定义规则相同。在缩进板块中编写函数体,最后用return返回一个值。

    求n的阶乘
    def f(x) :
        """
        计算阶乘
    
        :param x: 一个非负整数
    
        :return: x的阶乘
        """
        y = 1
        for n in range(1, x + 1) :
            y *= n
        # return表示返回一个值,同时结束此函数
        return y
    

    注意:函数内部一旦执行到return,该函数就会停止执行,并将结果返回。如果没有return语句,函数执行完毕就会停止,返回的是一个空值none。

    求最大公约数
    def gcd(x, y):
        """
        计算两个数的最大公约数
    
        :param x: 一个非负整数
        :param y: 一个非负整数
    
        :return: x,y的最大公约数
        """
        (x, y) = (y ,x) if x > y else (x, y)
        for factor in range(x, 0, -1):
            if x % factor == 0 and y % factor == 0:
                return factor
    
    判断素数
    def is_prime(x):
        """
        判断素数
    
        Parameters:
            x - 一个非负整数
            y - 一个非负整数
    
        Returns:
             如果num是素数返回True,反之返回False
        """
        for num in range (2,int(sqrt(x)) + 1):
            if x % num == 0:
                return False
        # return True
        # 排除1的写法:
        return True if x != 1 else False
    
    • 函数自变量的四种定义方式:

    1.不设定自变量

    def main():
        pass
    

    2.自变量为确定个数的参数,如上面的is_prime函数,自变量为1个,即x;gcd函数,自变量为2个,即x,y
    3.自变量为不确定的参数
    如下举例说明:
    在参数数量不确定的情况下,求多个数的和
    利用*args 定义可变参数:*args 参数数量不确定,可为0个,也可为多个。在调用函数add时,输入的自变量为多少个,函数就求多少个数的和。

    def add(*args):
        """
        参数数量不确定的情况下,求多个数的和
    
        :param argus:
            *args 定义可变参数:*args 参数数量不确定,可为0个,也可为多个
    
        :return: 多个参数的和
        """
        total = 0
        for value in args:
            total += value
        return total
    
    
    if __name__ == '__main__':
       # 直接传入可变参数
       # 求的是1+3+2+2+2+2的和
        print(add(1,3,2,2,2,2))
       # 传入列表,求列表中各个元素的和
        mylist = [1, 3, 5, 2, 10]
       # 如果传入的直接就是一个列表,必须在列表前面加上*,才能取到列表中各个元素,否则会被视为只传入了一个值,即列表
        print(add(*mylist))
    

    4.自变量设定了默认值
    定义摇n个色子,求每次色子点数之和的函数,假设我们给自变量一个默认值,可设置为“n=2”格式,如下:

    
    def roll_dice(n=2):
        total = 0
        for _ in range (n) :
            total += randint(1, 6)
        return total
    
    if __name__ == '__main__':
        # 调用函数,但未定义自变量,自变量取默认值2
        roll_dice()
        # 调用函数,定义自变量的值为3
        roll_dice(3)
    

    注意:在定义函数自变量时,官方建议不要用空格,如定义自变量为n,并给n赋一个默认值2,官方建议的书写格式为:n=2,而不是n = 2。但在其他情况下,官方建议的书写格式为:n = 2。


    空函数

    如果想定义一个什么事也不做的空函数,可以用pass语句。pass语句的意义:什么都不做,实际上是用来做占位符。比如现在还没有想好怎么写函数的代码,就可以先放一个pass,程序可以顺利运行。
    举例说明:

    def nop():
        pass
    

    pass还可以放在其他语句中,如:

    if x<1:
        pass
    

    函数的调用

    一个文件就是一个模块,一个模块中可能有1个或任意多个函数

    • 当前模块中调用函数

    调用函数时,若函数就在当前文本,则可以直接进行调用。格式为:函数名(变量)。由于很多时候这一个函数会被其他文本调用,为了让其他文本在调用此函数时不执行其他的代码,可以使用下面的if条件语句,让其他文本在导入此模块时不执行下面的代码,原理:只有本文件执行时,name = main,当其他文件执行时,name = 这个文件的命名,则name != main,if条件不成立,代码不执行。

    • 其他模块调用函数

    若当前文本需要调用其他文本的函数,则需要引入调用的函数模块。
    1.同一跟目录下的两个文本函数之间调用:from 要调用的函数所在文本的名称 import 函数名称
    2.不同根目录下的两个文本函数直接的调用:from 要调用的函数所在文本的路径(如day01.practice.prime,表示day01包下面的practice包下面的prime文本)import 函数名称
    3.一个文本可能存在多个函数,若需要调用此文本的所有函数,可写作如下格式:import combination * 导入combination中所有模块

    #导入 combination文件中所有模块
    import combination *
    

    4.直接引入函数所在文本,每次调用时再输入:文件名.函数名称。若原本的文件名太过复杂,还可临时给他命一个新的名字(别名):import combination as com 此处把combination命为com,在调用时,写作com.f

    import combination 
    #调用cobination的f(x)函数
    print(com.f(5))
    
    • 实例说明

    1.直接调用输出内容
    打印100以内的素数:
    if __name__ == '__main__':
        for num in range(1,100):
            # 当is_prime(num)函数返回的值为True时,if条件语句才会执行
            if is_prime(num):
                print(num)
    
    调用求阶乘函数:f(x),求组合数C(m, n)
        m = int(input('m = '))
        n = int(input('n = '))
        # 调用函数f(x)
        print(f(m) // f(n) // f(m - n))
    

    2.调用函数构造新的函数

    求最小公倍数,lcm函数调用cgd函数
    def lcm(x,y):
        """
        计算两个数的最小公倍数
    
        Parameters:
            x - 一个非负整数
            y - 一个非负整数
    
        Returns:
            x,y的最小公倍数
        """
        return x * y // gcd(x, y)
    

    3.函数的递归调用

    函数的递归调用指的是函数直接或间接调用函数自身,构造这样的递归函数必须满足以下几点:
    1.收敛条件 - 让递归在有限的次数完成或者进行回溯
    2.如果递归无法在有限次数内收敛就有可能导致RecursionError,而且栈的空间很小,必须控制此函数的递归深度在栈的递归深度内。
    3.递归公式
    在进入函数调用之前要保存当前的执行现场,函数的执行现场是保存在一种称为栈(stack)的内存空间上,栈是一种先进后出(FILO)的存储结构。所以函数在做递归调用时,会一层一层向下递归,最后在一层一层回溯。

    求最大公约数
    def gcd(x, y):
        if x > y:
            return gcd(y, x)
        elif y % x == 0:
            return x
        else:
            return gcd(y % x, x)
    
    求1到100的和
    def add(n):
        if n == 1 :
            return 1
        return n + add(n - 1)
    
    计算走楼梯有多少种方式

    10级楼梯,1次可选择1,2,3层台阶,走完这10层台阶,问有多少种走法

    def way(n):
        if n < 0:
            return 0
        elif n == 0:
            return 1
        return way(n - 1) + way(n - 2) + way(n - 3)
    
    汉诺塔
    def hanoi(n, a, b, c):
        if n > 0:
            hanoi(n - 1, a, c, b)
            print(a,'---->', b)
            hanoi(n - 1, c, b, a)
    

    函数命名冲突

    当有多个函数命名冲突时,后面的函数自动覆盖前面相同名称的函数。

    • 自己设定的函数和python内置的函数冲突:

    如自己编写了一个求最大公约数的函数gcd,和math中的内置的gcd函数冲突

    from combination import gcd,
    from math import gcd
    

    调用gcd函数时,如果直接书写gcd(),文本会自动调用写在后面的那个函数,如上就会调用math中的gcd,为了避免这种情况,可以按照以下方式调用:

    # 方法一
    import combination
    import math
    
    print(math.gcd())
    print(combination.gcd())
    
    # 方法二
    from combination import gcd
    # 调用的是conbinaion中的gcd函数
    print(gcd())
    from math import gcd
    # 调用的是math中的gcd函数
    print(gcd())
    

    函数变量的作用域

    变量的作用域有三种:
    1.全局(global)作用域的变量:定义在函数外部的变量,此变量可在全局范围内被调用
    2.嵌套(enclosed)作用域的变量:当一个函数调用另一个函数时,定义在外层函数中的变量,此变量可被内外层函数调用
    3.局部(local)作用域:当一个函数嵌套在另一个函数内部时,定义在内层函数中的变量,此变量只能被内层函数调用
    4.内置(build-in)作用域
    Python 搜索一个变量的方式是从局部作用域到嵌套作用域再到全局作用域,如果都没有搜索到,则会搜索内置函数,简称为LEGB(Local - Enclosed - Global - Build-in),如果想改变搜索范围,可以使用global和nonlocal关键字改变变量的作用域。
    举例说明:

    # 在函数外面定义的a是一个全局变量
    # 实际开发时一定要减少对全局变量的使用
    # global variable
    a = 100
    
    
    def foo():
        # 把foo函数内的变量a改为全局变量,这时如果在函数外调用a,当搜索到此处的a = 200时,原本变量a不能在函数外被调用,但此处变量a改为了全局变量,则能被函数外的代码调用
        global a
        a = 200
        # local variable
        # 函数内部的局部变量 离开foo函数变量是无法访问的
        b = 'hello'
    
        def bar():
            # 把局部作用域bar中的变量b改为嵌套作用域foo中的局部变量b,这时如果在foo中调用b,则搜索到的是b = 'good',而不是之前的b = 'hello'
            nonlocal b
            b = 'good'
            print(a)
            print(b)
    
        bar()
        print(b)
    
    
    # foo()函数运行结果:200 good good
    foo()
    # 运行结果:200
    print(a)
    
    

    相关文章

      网友评论

          本文标题:函数

          本文链接:https://www.haomeiwen.com/subject/nodhfftx.html