zoukankan      html  css  js  c++  java
  • python——函数

    定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可

    特性:

    1. 减少重复代码
    2. 使程序变的可扩展
    3. 使程序变得易维护

    一、语法定义

    def say_hi():
        print("hello world")
    
    
    say_hi()  # 调用函数

    二、函数的参数

    def calc(x, y):
        res = x**y
        return res  # 返回函数执行结果
    
    
    c = calc(2, 3)  # 结果赋值给c变量
    print(c)
    View Code

    形参

    只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。

    实参

    可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值。

    默认参数

    看如下代码:

    def stu_register(name,age,country,course):
        print("----注册学生信息------")
        print("姓名:",name)
        print("age:",age)
        print("国籍:",country)
        print("课程:",course)
    
    stu_register("王山炮",22,"CN","python_devops")
    stu_register("张叫春",21,"CN","linux")
    stu_register("刘老根",25,"CN","linux")
    View Code

    发现 country 这个参数 基本都 是"CN", 就像我们在网站上注册用户,像国籍这种信息,你不填写,默认就会是 中国, 这就是通过默认参数实现的,把country变成默认参数非常简单:

    def stu_register(name,age,course,country="CN"):

    这样,这个参数在调用时不指定,那默认就是CN,指定了的话,就用你指定的值。

    另外,你可能注意到了,在把country变成默认参数后,我同时把它的位置移到了最后面,为什么呢?

    这就要谈到 “关键参数”了。

    关键参数

    正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可(指定了参数名的参数就叫关键参数),但记住一个要求就是,关键参数必须放在位置参数(以位置顺序确定对应关系的参数)之后。

    def stu_register(name, age, course='PY' ,country='CN'):
        print("----注册学生信息------")
        print("姓名:", name)
        print("age:", age)
        print("国籍:", country)
        print("课程:", course)
    View Code

    调用时
    可以这样写:

    stu_register("王山炮",course='PY', age=22,country='JP' )

    但不能这样:

    stu_register("王山炮",course='PY',22,country='JP' )

    关键参数不可以放在未知参数之前,否则会报错。

    也不能这样:

    stu_register("王山炮",22,age=25,country='JP' )

    相当于给age两次赋值,会报错。


    非固定参数

    若你的函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数:*args,**kwargs。

    def stu_register(name, age, *args):  # *args 会把多传入的参数变成一个元组形式
        print(name, age, args)
    
    
    stu_register("Henry", 22, "IT", "2018-05-08")
    
    
    输出:
    Henry 22 ('IT', '2018-05-08')
    View Code
    def stu_register(name,age,*args,**kwargs):  # *kwargs 会把多传入的参数变成一个dict形式
        print(name,age,args,kwargs)
    
    
    stu_register("Jack",32,"CN","Python",sex="Male",province="ShanDong")
    
    输出:
    Jack 32 ('CN', 'Python') {'sex': 'Male', 'province': 'ShanDong'}  # 后面这个('CN', 'Python')就是args,{'sex': 'Male', 'province': 'ShanDong'}就是kwargs
    View Code

    返回值
    函数外部的代码要想获取函数的执行结果,就可以在函数里用return语句把结果返回

    def stu_register(name, age, course='PY', country='CN'):
        print("----注册学生信息------")
        print("姓名:", name)
        print("age:", age)
        print("国籍:", country)
        print("课程:", course)
        if age > 22:
            return False
        else:
            return True
    
    
    registriation_status = stu_register("王山炮",22,course="PY全栈开发",country='JP')
    
    if registriation_status:
        print("注册成功")
    else:
        print("too old to be a student.")
    View Code
    • 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,因此,可以理解为 return 语句代表着函数的结束
    • 如果未在函数中指定return,那这个函数的返回值为None

    全局与局部变量

    • 在函数中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
    • 全局变量作用域是整个程序,局部变量作用域是定义该变量的函数。
    • 当全局变量与局部变量同名时,在定义局部变量的函数内,局部变量起作用;在其它地方全局变量起作用。
    • 可以在函数里面可以调用外面的全局变量,但不能修改全局变量。
    • 两个同级的独立的函数中相同名字的变量是互不相干的,不会存在相互调用等现象。
    name = "Alex"
    
    
    def change_name(name):
        print("before change:", name)
        name = "Jack"
        print("after change", name)
    
    
    change_name(name)
    
    print("在外面看看name改了么?",name)
    
    
    输出:
    before change: Alex
    after change Jack
    在外面看看name改了么? Alex
    View Code

    在程序运行完后,name的值依然没有改变,那么有没有办法让它改变呢??
    当然有啦!改变它的作用域就可以了。

    作用域

      在python中,一个函数就是一个作用域,函数定义完成或作用域就已经生成。

    如何在函数里修改全局变量:

    name = "Alex"
    
    
    def change_name():
        global name  # 将name改为全局变量
        print("before change:", name)
        name = "Jack"
        print("after change", name)
    
    
    change_name()
    print("在外面看看name改了么?", name)
    
    输出:
    before change: Alex
    after change Jack
    在外面看看name改了么? Jack
    View Code

    在函数内部将name定义为全局变量,这样就可以改变它的值了。
    其他作用域示例:

    names = ["luara", "jason", "henry"]
    
    
    def change_name():
        names = ["luara", "jason"]
        print("after change:", names)
    change_name()
    print("outer:", names)
    
    输出:
    after change: ['luara', 'jason']
    outer: ['luara', 'jason', 'henry']
    View Code
    names = ["luara", "jason", "henry"]
    
    
    def change_name():
        del names[2]
        print("after change:", names)
    
    
    change_name()
    print("outer:", names)
    
    输出:
    after change: ['luara', 'jason']
    outer: ['luara', 'jason']
    View Code

    从以上两个程序运行结果发现,第二个程序的names被改变了,为什么呢?
    原因是:与之前讲的深浅copy一个道理,一个列表就有一个自己的内存地址,而其里面的元素又有它们自己单独的内存地址,在函数内对列表整体进行修改时,不会影响外层的names,但对列表内的元素进行操作时,便会影响外层的names。类似的还有字典、类、集合等。

    age = 19
    
    
    def func1():
        age = 73
    
        def func2():
            print("func2:", age)
        return func2  # 返回一个函数名
    
    
    val = func1()  # val获取到了func2的内存地址
    print(val)
    val()  # 此时相当于执行func2()
    
    输出:
    <function func1.<locals>.func2 at 0x0000000001E59AE8>  # 打印了func2的内存地址
    func2: 73
    View Code

    嵌套函数
      在一个函数体内用“def”定义了另外一个函数就叫嵌套函数。

    def func1():
        print("alex")
    
        def func2():
            print("eric")
    
    
    func1()
    
    输出:
    alex
    View Code

    发现内层的函数func2没有执行,因为程序没有调用它,一个函数如果没有被调用,它是永远不会执行的。

    def func1():
        print("alex")
    
        def func2():
            print("eric")
    
    
        func2()  # 调用func2
    
    
    func1()  # 调用func1
    
    
    输出:
    alex
    eric
    View Code
    age = 19
    
    
    def func1():
        age = 73
        print("func1:", age)
    
        def func2():
            print("func2:", age)
    
        func2()
    
        
    func1()
    
    输出:
    73
    73
    View Code
    age = 19
    
    
    def func1():
    
        def func2():
            print("func2:", age)
        age = 73
        func2()
    
    
    func1()
    
    输出:
    func2: 73
    View Code

    在函数执行过程中,如果在自己内部没有找到age,它就会去它的外面一层找,若找到了就打印,若没有找到,就会接着再往外寻找,直到找到为止。
    所以说,嵌套函数是从内到外,逐层寻找

    匿名函数

      不需要显示的指定函数名的函数就叫匿名函数。

    语法:

    lambda 参数:表达式

    如下代码:

    def calc(x, y):
        return x * y
    
    
    print(calc(2, 3))

    可以用匿名函数改写为:

    calc = lambda x,y: x * y
    print(calc(2, 3))

    匿名函数三元运算:

    calc = lambda x, y: x if x > y else y
    print(calc(3, 1))

    匿名函数主要与其他函数搭配使用:

    res = list(map(lambda x: x**2, [1, 2, 3, 4]))
    print(res)
    
    输出:
    [1, 4, 9, 16]

    高阶函数
    变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就叫高阶函数。

    def add(x, y, f):
        return f(x) + f(y)  # 相当于abs(4) + abs(-9)
    
    
    res = add(4, -9, abs)
    print(res)
    
    输出:
    13
    View Code

    只需满足以下任意一个条件,即是高阶函数:

    • 接收一个或多个函数名作为参数输入
    • return 返回另外一个函数(返回值中包含函数名)

     递归函数

    如果一个函数在内部调用自身本身,这个函数就是递归函数。

    递归函数示例:n的阶乘,这是我认为最能直观理解递归执行过程的示例

    def fact(n):
        if n == 1:
            return 1  # 当n=1时结束递归
        return n * fact(n-1)
    
    
    res = fact(5)
    print(res)
    View Code

    函数执行过程:

    在n=1之前,函数将一直被挂起,直到遇到结束条件,函数再一层一层返回。

    传入一个数,只执行5次就结束:

    def calc(n, count):
        print("n:{},   count:{}".format(n, count))
        if count < 5:
            return calc(n/2, count+1)
        else:
            return n  # 如果count>5 就返回当前的n值
    
    
    res = calc(188, 0)
    print("程序结束时的n值:", res)
    
    输出:
    n:188,   count:0
    n:94.0,   count:1
    n:47.0,   count:2
    n:23.5,   count:3
    n:11.75,   count:4
    n:5.875,   count:5
    程序结束时的n值: 5.875
    View Code

    递归特性:

    1. 必须有一个明确的结束条件
    2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
    3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

    堆栈扫盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html

    递归函数实际应用案例,二分查找

    # 使用二分法查找列表中的某个数据
    li = [2, 3, 6, 44, 34, 78, 67, 77, 90, 345, 67, 39, 100, 104, 209, 56, 789, 290, 62]
    
    
    def find(li1, num):
        print(li1)
        n = int(len(li1)/2)  # 列表长度折半
        if n >= 1:  # 列表元素大于1
            if num < li1[n]:  # 数字在列表左边
                print("the number is in the left of the list")
                return find(li1[0:n], num)
            elif num > li1[n]:  # 数字在列表右边
                print("the number is in the right of the list")
                return find(li1[n+1:], num)
            elif num == li1[n]:
                print("find the number:", li1[n])
        else:
            if num == li1[n]:
                print("find the number:", li1[n])
            else:
                print("the number is not existed!")
    
    
    li.sort()  # 列表元素排序
    print(li)
    find_num = int(input("input the number you want to find:"))
    find(li, find_num)
    View Code

    内置函数

    内置参数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii

     

  • 相关阅读:
    用户调查报告
    beta冲刺总结
    beta冲刺第七天
    beta冲刺第六天
    beta冲刺第五天
    beta冲刺第四天
    beta冲刺第三天
    beta冲刺第二天
    beta冲刺第一天
    简单的密码管理器(Python)(待完善)
  • 原文地址:https://www.cnblogs.com/yanlin-10/p/9011612.html
Copyright © 2011-2022 走看看