zoukankan      html  css  js  c++  java
  • 7.*函数的参数

    函数

    为什么要定义函数

    1. 代码冗余
    2. 不方便管理,维护性差
    3. 组织结构差

    函数分类

    内置函数

    https://docs.python.org/3/library/functions.html#abs

    自定义函数

    def func_1():
        #func_1 function
        pass

    print(func_1.__doc__)
    用于显示函数注释

    函数也分有参函数和无参函数,
    定义时有参数,就需要传入参数;
    定义时没有参数,就不需要传入参数
    这其中还涉及到默认参数等,在下文的参数中详解

    返回值/返回函数

    函数的返回值可以是任何类型

    当函数没有return ,返回的是None

    这也是有些函数运行之后,会在解释器中返回一个NONE的原因

    函数返回值

    #return
    def bar (x,y):
        return 1,2,3

    单个函数只能执行一次return,return就类似一个break一样,给出一个结果并且结束程序
    上面函数的返回值为一个元组(1,2,3)

    python在默认使用“,”的时候,会构建一个元组

    当你需要逐个获取返回值的时候

    a,b,c = bar(x,y)
    >>>
    a=1
    b=2
    c=3

    以上就是一种获取返回结果的方法,这种情况用于接收多个由函数生成的值。

    范例:

    a,*_,b = 'thisisastring'
    a = t
    b = g

    返回函数

    有时候在函数定义完之后,发现并不需要立即传参进行计算,而是在后面的代码中,根据需要再进行计算。
    这时候就可以不返回计算的结果,而是返回计算的函数:

    def lazy_max():
        def max(a,b):
            if a>b:
                print(a)
            elif a<b:
                print(b)
            else:
                print(a,'=',b)
        return max
    
    print(lazy_max()(1,5))

    相关参数和变量都保存在返回的函数中,这种称为闭包(closure)

    闭包

    之前在装饰器的笔记里写到过闭包,但是那时候的理解还在猜测阶段,没有一个清晰的定义。
    所以在这里重新声明一下:
    闭包就是把相关参数和变量都保存在返回的函数中,当一个函数返回一个函数后,其内部的局部变量还被新函数引用,返回的函数也没有立即执行,直到调用了()才执行

    在python中,被定义过的函数名(如果不需要传参)后直接跟上()就能将函数运行起来。甚至在这个函数名被赋值给其他的变量后,获得赋值的变量也同样有这种特性

    >>> def func():
    …     print('hello babe')
    …
    >>> z = func
    >>> z()
    hello babe

    函数的参数介绍

    在函数定义阶段,括号内定义的参数,就是形参
    在函数调用阶段,括号内定义的参数,就是实参

    一定要注意函数的两个阶段,定义阶段不运行,不会给出结果,也不做任何操作。

    其实以上的定义也并不完全准确。真正的形参和实参有更加准确的描述,上述描述在例如x=23这种情况下就不适用,因为赋值的时候并不涉及到函数。

    位置参数

    这个概念比较粗糙,其实大部分存在的参数,我们都可以考虑叫他位置参数(由于在python中按位置传参的确很方便,也很普遍)。在有参函数中,如果不指定特定的关键字,甚至有默认的关键字参数,在不添加关键字的时候,默认按照位置参数来进行传参。

    根据位置传值,必须在关键字参数前面!!!并且只能使用一种方式对同个参数进行传值,必须进行传值,需要准确传值,参数不能多也不能少。

    按位置传值

    比方说:

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

    这是一个修改后的power()函数,可以计算任意的n次方
    这其中有两个参数,power(x,n),这两个参数都是位置参数,调用函数时,传入的两个值按照位置顺序依次赋给x,n

    默认参数

    power(5)
    TypeError: power() missing 1 required positional argument: 'n'

    报错:缺少一个参数
    默认参数:调用时,无需传值

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

    以上代码,我们在定义阶段就默认定义n=2,从而在真的使用该函数的时候。当我们默认使用单个参数的时候:

    >>>power(5)
    25

    定义函数的时候,我们使用默认参数来定义一些,变动比较小的参数,可以在传参的时候节省力气。
    定义规则:当函数有多个参数的时候,把变化大的参数放在前面,变化小的参数放在后面

    可变参数

    *args``**kw

    def calc(number):
        sum = 0
        for n in number:
            sum = sum+ n*n
        return sum

    在使用上面的函数的时候,我们传入的num因为需要被迭代,所以num的类型必须是list或者tuple

    例如calc([1,2,4,5,3,8])

    如果使用可变参数,调用的方式就会简单很多:calc(1,2,5,43,8)

    所以我们可以修改函数定义参数为可变参数

    def calc(*numbers):
        pass

    这里比较需要注意的就是,位置参数和可变参数的混用。

    def calc(x,y = 1,*numbers):
        pass

    calc(1,2,4,5,7,8,6,3,8,2,4,5)
    可以发现,x,y原本是默认值,被传参之后,取得了1,2,而剩下的数字,被作为一个元组,合并进了numbers

    >>> def calc(x,y = 1,*numbers):
    …     print(x)
    …     print(y)
    …     print(numbers)
    …
    >>> calc(1,2,4,5,78,8,6,3,5)
    1
    2
    (4, 5, 78, 8, 6, 3, 5)

    著名鲁派清口导师egon曾经说过:‘*’后面的可变参数,在使用的时候,就把其中的元素打散了看。

    从实参的角度进行测试

    >>> def bar(x,y,z):
    …     print(x)
    …     print(y)
    …     print(z)
    …
    >>> bar(*(1,2,3,4))
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: bar() takes 3 positional arguments but 4 were given

    上述我们已经使用了*args,会把后面的按位置传值的参数整合成一个tuple
    而**kwargs,就是把后面的关键字传值的参数整合成一个dict

    >>> def bar(x,y,z):
    …     print(x)
    …     print(y)
    …     print(z)
    …
    >>> bar(*(1,2,3,4))
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: bar() takes 3 positional arguments but 4 were given
    
    
    
    >>> def foo(x,*args,**kwargs):
    …     print(x)
    …     print(args)
    …     print(kwargs)
    …
    >>>
    >>>
    >>> foo(1,y=3,z=5)
    1
    ()
    {'y': 3, 'z': 5}

    <wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

  • 相关阅读:
    Mixtile LOFT
    关于Linux系统清理/tmp/文件夹的原理
    在大型项目上,Python 是个烂语言吗
    Nginx 进程间通信
    蕤仁肉(内仁肉、泪仁肉)简单介绍
    TMS320F28335项目开发记录5_28335之CCS编程基础
    RBAC权限管理
    国内三大PT(Private Tracker)站分析
    Nginx特点
    java设计模式演示样例
  • 原文地址:https://www.cnblogs.com/scott-lv/p/7468933.html
Copyright © 2011-2022 走看看